From 88da98e37b9539c103ae9e6fc7db1b4e52010585 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 31 Jul 2007 20:32:15 +0000 Subject: [PATCH 01/14] Move top-level boost directory over to "devel" (temporarily) [SVN r38327] --- .gitattributes | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3e84d7c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain From 97843bcaeffaba00bbf58f3ded236dfe5d523154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 26 Aug 2011 18:25:51 +0000 Subject: [PATCH 02/14] First inclusion in the repository [SVN r74076] --- include/boost/container/container_fwd.hpp | 198 ++ include/boost/container/deque.hpp | 1881 +++++++++++ .../detail/adaptive_node_pool_impl.hpp | 648 ++++ .../container/detail/advanced_insert_int.hpp | 385 +++ include/boost/container/detail/algorithms.hpp | 215 ++ .../container/detail/allocation_type.hpp | 54 + .../boost/container/detail/config_begin.hpp | 48 + include/boost/container/detail/config_end.hpp | 17 + include/boost/container/detail/destroyers.hpp | 154 + include/boost/container/detail/flat_tree.hpp | 858 +++++ include/boost/container/detail/iterators.hpp | 546 ++++ .../boost/container/detail/math_functions.hpp | 113 + include/boost/container/detail/mpl.hpp | 155 + .../detail/multiallocation_chain.hpp | 252 ++ .../container/detail/node_alloc_holder.hpp | 501 +++ .../boost/container/detail/node_pool_impl.hpp | 367 +++ include/boost/container/detail/pair.hpp | 320 ++ .../boost/container/detail/pool_common.hpp | 52 + .../boost/container/detail/preprocessor.hpp | 141 + include/boost/container/detail/stored_ref.hpp | 92 + .../container/detail/transform_iterator.hpp | 176 ++ include/boost/container/detail/tree.hpp | 1064 +++++++ .../boost/container/detail/type_traits.hpp | 203 ++ include/boost/container/detail/utilities.hpp | 150 + include/boost/container/detail/value_init.hpp | 43 + .../detail/variadic_templates_tools.hpp | 153 + .../boost/container/detail/version_type.hpp | 92 + include/boost/container/detail/workaround.hpp | 24 + include/boost/container/flat_map.hpp | 1443 +++++++++ include/boost/container/flat_set.hpp | 1261 ++++++++ include/boost/container/list.hpp | 1373 ++++++++ include/boost/container/map.hpp | 1292 ++++++++ include/boost/container/set.hpp | 1163 +++++++ include/boost/container/slist.hpp | 1536 +++++++++ include/boost/container/stable_vector.hpp | 1697 ++++++++++ include/boost/container/string.hpp | 2786 +++++++++++++++++ include/boost/container/vector.hpp | 1999 ++++++++++++ 37 files changed, 23452 insertions(+) create mode 100644 include/boost/container/container_fwd.hpp create mode 100644 include/boost/container/deque.hpp create mode 100644 include/boost/container/detail/adaptive_node_pool_impl.hpp create mode 100644 include/boost/container/detail/advanced_insert_int.hpp create mode 100644 include/boost/container/detail/algorithms.hpp create mode 100644 include/boost/container/detail/allocation_type.hpp create mode 100644 include/boost/container/detail/config_begin.hpp create mode 100644 include/boost/container/detail/config_end.hpp create mode 100644 include/boost/container/detail/destroyers.hpp create mode 100644 include/boost/container/detail/flat_tree.hpp create mode 100644 include/boost/container/detail/iterators.hpp create mode 100644 include/boost/container/detail/math_functions.hpp create mode 100644 include/boost/container/detail/mpl.hpp create mode 100644 include/boost/container/detail/multiallocation_chain.hpp create mode 100644 include/boost/container/detail/node_alloc_holder.hpp create mode 100644 include/boost/container/detail/node_pool_impl.hpp create mode 100644 include/boost/container/detail/pair.hpp create mode 100644 include/boost/container/detail/pool_common.hpp create mode 100644 include/boost/container/detail/preprocessor.hpp create mode 100644 include/boost/container/detail/stored_ref.hpp create mode 100644 include/boost/container/detail/transform_iterator.hpp create mode 100644 include/boost/container/detail/tree.hpp create mode 100644 include/boost/container/detail/type_traits.hpp create mode 100644 include/boost/container/detail/utilities.hpp create mode 100644 include/boost/container/detail/value_init.hpp create mode 100644 include/boost/container/detail/variadic_templates_tools.hpp create mode 100644 include/boost/container/detail/version_type.hpp create mode 100644 include/boost/container/detail/workaround.hpp create mode 100644 include/boost/container/flat_map.hpp create mode 100644 include/boost/container/flat_set.hpp create mode 100644 include/boost/container/list.hpp create mode 100644 include/boost/container/map.hpp create mode 100644 include/boost/container/set.hpp create mode 100644 include/boost/container/slist.hpp create mode 100644 include/boost/container/stable_vector.hpp create mode 100644 include/boost/container/string.hpp create mode 100644 include/boost/container/vector.hpp diff --git a/include/boost/container/container_fwd.hpp b/include/boost/container/container_fwd.hpp new file mode 100644 index 0000000..f304382 --- /dev/null +++ b/include/boost/container/container_fwd.hpp @@ -0,0 +1,198 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_CONTAINERS_FWD_HPP +#define BOOST_CONTAINERS_CONTAINERS_FWD_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +////////////////////////////////////////////////////////////////////////////// +// Standard predeclarations +////////////////////////////////////////////////////////////////////////////// + +/// @cond + +namespace boost{ +namespace intrusive{ + //Create namespace to avoid compilation errors +}} + +namespace boost{ namespace container{ namespace containers_detail{ + +namespace bi = boost::intrusive; + +}}} + +#ifndef _LIBCPP_VERSION + +namespace std { + +template +class allocator; + +template +struct less; + +template +struct pair; + +template +struct char_traits; + +} //namespace std { + +#else + +#include +#include +#include +#include + +#endif + +/// @endcond + +////////////////////////////////////////////////////////////////////////////// +// Containers +////////////////////////////////////////////////////////////////////////////// + +namespace boost { +namespace container { + +//vector class +template > +class vector; + +//vector class +template > +class stable_vector; + +//vector class +template > +class deque; + +//list class +template > +class list; + +//slist class +template > +class slist; + +//set class +template + ,class A = std::allocator > +class set; + +//multiset class +template + ,class A = std::allocator > +class multiset; + +//map class +template + ,class A = std::allocator > > +class map; + +//multimap class +template + ,class A = std::allocator > > +class multimap; + +//flat_set class +template + ,class A = std::allocator > +class flat_set; + +//flat_multiset class +template + ,class A = std::allocator > +class flat_multiset; + +//flat_map class +template + ,class A = std::allocator > > +class flat_map; + +//flat_multimap class +template + ,class A = std::allocator > > +class flat_multimap; + +//basic_string class +template + ,class A = std::allocator > +class basic_string; + +//! Type used to tag that the input range is +//! guaranteed to be ordered +struct ordered_range_impl_t {}; + +//! Type used to tag that the input range is +//! guaranteed to be ordered and unique +struct ordered_unique_range_impl_t{}; + +/// @cond + +typedef ordered_range_impl_t * ordered_range_t; +typedef ordered_unique_range_impl_t *ordered_unique_range_t; + +/// @endcond + +//! Value used to tag that the input range is +//! guaranteed to be ordered +static const ordered_range_t ordered_range = 0; + +//! Value used to tag that the input range is +//! guaranteed to be ordered and unique +static const ordered_unique_range_t ordered_unique_range = 0; + +/// @cond + +namespace detail_really_deep_namespace { + +//Otherwise, gcc issues a warning of previously defined +//anonymous_instance and unique_instance +struct dummy +{ + dummy() + { + (void)ordered_range; + (void)ordered_unique_range; + } +}; + +} //detail_really_deep_namespace { + +/// @endcond + +}} //namespace boost { namespace container { + +#endif //#ifndef BOOST_CONTAINERS_CONTAINERS_FWD_HPP diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp new file mode 100644 index 0000000..b890057 --- /dev/null +++ b/include/boost/container/deque.hpp @@ -0,0 +1,1881 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_DEQUE_HPP +#define BOOST_CONTAINERS_DEQUE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace container { + +/// @cond +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template > +#else +template +#endif +class deque; + +template +struct deque_value_traits +{ + typedef T value_type; + typedef A allocator_type; + static const bool trivial_dctr = boost::has_trivial_destructor::value; + static const bool trivial_dctr_after_move = false; + //::boost::has_trivial_destructor_after_move::value || trivial_dctr; + static const bool trivial_copy = has_trivial_copy::value; + static const bool nothrow_copy = has_nothrow_copy::value; + static const bool trivial_assign = has_trivial_assign::value; + static const bool nothrow_assign = has_nothrow_assign::value; + +}; + +// 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); } + +// 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 deque_base +{ + public: + typedef typename A::value_type val_alloc_val; + typedef typename A::pointer val_alloc_ptr; + typedef typename A::const_pointer val_alloc_cptr; + typedef typename A::reference val_alloc_ref; + typedef typename A::const_reference val_alloc_cref; + typedef typename A::difference_type val_alloc_diff; + typedef typename A::size_type val_alloc_size; + typedef typename A::template rebind + ::other ptr_alloc_t; + typedef typename ptr_alloc_t::value_type ptr_alloc_val; + typedef typename ptr_alloc_t::pointer ptr_alloc_ptr; + typedef typename ptr_alloc_t::const_pointer ptr_alloc_cptr; + typedef typename ptr_alloc_t::reference ptr_alloc_ref; + typedef typename ptr_alloc_t::const_reference ptr_alloc_cref; + typedef typename A::template + rebind::other allocator_type; + typedef allocator_type stored_allocator_type; + typedef val_alloc_size size_type; + + protected: + + typedef deque_value_traits traits_t; + typedef typename A::template + rebind::other map_allocator_type; + + static size_type s_buffer_size() { return deque_buf_size(sizeof(T)); } + + val_alloc_ptr priv_allocate_node() + { return this->alloc().allocate(s_buffer_size()); } + + void priv_deallocate_node(val_alloc_ptr p) + { this->alloc().deallocate(p, s_buffer_size()); } + + ptr_alloc_ptr priv_allocate_map(size_type n) + { return this->ptr_alloc().allocate(n); } + + void priv_deallocate_map(ptr_alloc_ptr p, size_type n) + { this->ptr_alloc().deallocate(p, n); } + + 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 + { + public: + static size_type s_buffer_size() { return deque_base::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; + friend class deque_base; + + 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); + } + + 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; + } + + self_t operator++(int) + { + self_t tmp = *this; + ++*this; + return tmp; + } + + 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; + } + + self_t operator--(int) + { + self_t 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; + } + + 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); } + + bool operator==(const self_t& x) const + { return this->m_cur == x.m_cur; } + + bool operator!=(const self_t& x) const + { return !(*this == x); } + + 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); + } + + bool operator>(const self_t& x) const + { return x < *this; } + + bool operator<=(const self_t& x) const + { return !(x < *this); } + + bool operator>=(const self_t& x) const + { return !(*this < x); } + + 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 const_iterator operator+(difference_type n, const const_iterator& x) + { return x + n; } + }; + + //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 class deque; + friend class deque_base; + + private: + explicit iterator(const const_iterator& x) : const_iterator(x){} + + 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){} + + //Pointer like operators + reference operator*() const { return *this->m_cur; } + pointer operator->() const { return this->m_cur; } + + reference operator[](difference_type n) const { return *(*this + n); } + + //Increment / Decrement + iterator& operator++() + { this->const_iterator::operator++(); return *this; } + + iterator operator++(int) + { iterator tmp = *this; ++*this; return tmp; } + + iterator& operator--() + { this->const_iterator::operator--(); return *this; } + + iterator operator--(int) + { iterator tmp = *this; --*this; return tmp; } + + // Arithmetic + iterator& operator+=(difference_type off) + { this->const_iterator::operator+=(off); return *this; } + + iterator operator+(difference_type off) const + { return iterator(this->const_iterator::operator+(off)); } + + friend iterator operator+(difference_type off, const iterator& right) + { return iterator(off+static_cast(right)); } + + iterator& operator-=(difference_type off) + { this->const_iterator::operator-=(off); return *this; } + + iterator operator-(difference_type off) const + { return iterator(this->const_iterator::operator-(off)); } + + difference_type operator-(const const_iterator& right) const + { return static_cast(*this) - right; } + }; + + deque_base(const allocator_type& a, size_type num_elements) + : members_(a) + { this->priv_initialize_map(num_elements); } + + deque_base(const allocator_type& a) + : members_(a) + {} + + ~deque_base() + { + if (this->members_.m_map) { + this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1); + this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); + } + } + + private: + deque_base(const deque_base&); + + protected: + + void priv_initialize_map(size_type num_elements) + { +// if(num_elements){ + size_type num_nodes = num_elements / s_buffer_size() + 1; + + this->members_.m_map_size = containers_detail::max_value((size_type) InitialMapSize, num_nodes + 2); + this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size); + + ptr_alloc_ptr nstart = this->members_.m_map + (this->members_.m_map_size - num_nodes) / 2; + ptr_alloc_ptr nfinish = nstart + num_nodes; + + BOOST_TRY { + this->priv_create_nodes(nstart, nfinish); + } + BOOST_CATCH(...){ + this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); + this->members_.m_map = 0; + this->members_.m_map_size = 0; + BOOST_RETHROW + } + BOOST_CATCH_END + + this->members_.m_start.priv_set_node(nstart); + this->members_.m_finish.priv_set_node(nfinish - 1); + this->members_.m_start.m_cur = this->members_.m_start.m_first; + this->members_.m_finish.m_cur = this->members_.m_finish.m_first + + num_elements % s_buffer_size(); +// } + } + + void priv_create_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) + { + ptr_alloc_ptr cur; + BOOST_TRY { + for (cur = nstart; cur < nfinish; ++cur) + *cur = this->priv_allocate_node(); + } + BOOST_CATCH(...){ + this->priv_destroy_nodes(nstart, cur); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) + { + for (ptr_alloc_ptr n = nstart; n < nfinish; ++n) + this->priv_deallocate_node(*n); + } + + void priv_clear_map() + { + if (this->members_.m_map) { + this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1); + this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); + this->members_.m_map = 0; + this->members_.m_map_size = 0; + this->members_.m_start = iterator(); + this->members_.m_finish = this->members_.m_start; + } + } + + enum { InitialMapSize = 8 }; + + protected: + struct members_holder + : public ptr_alloc_t + , public allocator_type + { + members_holder(const allocator_type &a) + : map_allocator_type(a), allocator_type(a) + , m_map(0), m_map_size(0) + , m_start(), m_finish(m_start) + {} + + ptr_alloc_ptr m_map; + typename allocator_type::size_type m_map_size; + iterator m_start; + iterator m_finish; + } members_; + + ptr_alloc_t &ptr_alloc() + { return members_; } + + const ptr_alloc_t &ptr_alloc() const + { return members_; } + + allocator_type &alloc() + { return members_; } + + const allocator_type &alloc() const + { return members_; } +}; +/// @endcond + +//! Deque class +//! +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template > +#else +template +#endif +class deque : protected deque_base +{ + /// @cond + typedef deque_base Base; + + public: // Basic types + typedef typename A::value_type val_alloc_val; + typedef typename A::pointer val_alloc_ptr; + typedef typename A::const_pointer val_alloc_cptr; + typedef typename A::reference val_alloc_ref; + typedef typename A::const_reference val_alloc_cref; + typedef typename A::size_type val_alloc_size; + typedef typename A::difference_type val_alloc_diff; + + typedef typename A::template + rebind::other ptr_alloc_t; + typedef typename ptr_alloc_t::value_type ptr_alloc_val; + typedef typename ptr_alloc_t::pointer ptr_alloc_ptr; + typedef typename ptr_alloc_t::const_pointer ptr_alloc_cptr; + typedef typename ptr_alloc_t::reference ptr_alloc_ref; + typedef typename ptr_alloc_t::const_reference ptr_alloc_cref; + /// @endcond + + 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_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + /// @cond + + private: // Internal typedefs + BOOST_COPYABLE_AND_MOVABLE(deque) + typedef ptr_alloc_ptr index_pointer; + static size_type s_buffer_size() + { return Base::s_buffer_size(); } + typedef containers_detail::advanced_insert_aux_int advanced_insert_aux_int_t; + typedef repeat_iterator r_iterator; + typedef boost::move_iterator move_it; + + /// @endcond + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + allocator_type get_allocator() const { return Base::alloc(); } + + public: // Basic accessors + + //! Effects: Returns an iterator to the first element contained in the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return this->members_.m_start; } + + //! Effects: Returns an iterator to the end of the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return this->members_.m_finish; } + + //! Effects: Returns a const_iterator to the first element contained in the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return this->members_.m_start; } + + //! Effects: Returns a const_iterator to the end of the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return this->members_.m_finish; } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return reverse_iterator(this->members_.m_finish); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return reverse_iterator(this->members_.m_start); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return const_reverse_iterator(this->members_.m_finish); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return const_reverse_iterator(this->members_.m_start); } + + //! Effects: Returns a const_iterator to the first element contained in the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return this->members_.m_start; } + + //! Effects: Returns a const_iterator to the end of the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return this->members_.m_finish; } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const + { return const_reverse_iterator(this->members_.m_finish); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return const_reverse_iterator(this->members_.m_start); } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference operator[](size_type n) + { return this->members_.m_start[difference_type(n)]; } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference operator[](size_type n) const + { return this->members_.m_start[difference_type(n)]; } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + reference at(size_type n) + { this->priv_range_check(n); return (*this)[n]; } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + const_reference at(size_type n) const + { this->priv_range_check(n); return (*this)[n]; } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference front() { return *this->members_.m_start; } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference front() const + { return *this->members_.m_start; } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the last + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference back() { return *(end()-1); } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the last + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference back() const { return *(cend()-1); } + + //! Effects: Returns the number of the elements contained in the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return this->members_.m_finish - this->members_.m_start; } + + //! Effects: Returns the largest possible size of the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return this->alloc().max_size(); } + + //! Effects: Returns true if the deque contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return this->members_.m_finish == this->members_.m_start; } + + //! Effects: Constructs a deque taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + explicit deque(const allocator_type& a = allocator_type()) + : Base(a) + {} + + //! Effects: Constructs a deque that will use a copy of allocator a + //! and inserts n default contructed values. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + explicit deque(size_type n) : Base(allocator_type(), n) + { + containers_detail::default_construct_aux_proxy proxy(n); + proxy.uninitialized_copy_all_to(this->begin()); + //deque_base will deallocate in case of exception... + } + + //! Effects: Constructs a deque that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + deque(size_type n, const value_type& value, + const allocator_type& a = allocator_type()) : Base(a, n) + { this->priv_fill_initialize(value); } + + //! Effects: Copy constructs a deque. + //! + //! Postcondition: x == *this. + //! + //! Complexity: Linear to the elements x contains. + deque(const deque& x) + : Base(x.alloc()) + { + if(x.size()){ + this->priv_initialize_map(x.size()); + std::uninitialized_copy(x.begin(), x.end(), this->members_.m_start); + } + } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + deque(BOOST_RV_REF(deque) mx) + : Base(mx.alloc()) + { this->swap(mx); } + + //! Effects: Constructs a deque that will use a copy of allocator a + //! and inserts a copy of the range [first, last) in the deque. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's constructor taking an dereferenced InIt throws. + //! + //! Complexity: Linear to the range [first, last). + template + deque(InpIt first, InpIt last, const allocator_type& a = allocator_type()) + : Base(a) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_initialize_dispatch(first, last, Result()); + } + + //! Effects: Destroys the deque. All stored values are destroyed + //! and used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements. + ~deque() + { + priv_destroy_range(this->members_.m_start, this->members_.m_finish); + } + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + deque& operator= (BOOST_COPY_ASSIGN_REF(deque) x) + { + const size_type len = size(); + if (&x != this) { + if (len >= x.size()) + this->erase(std::copy(x.begin(), x.end(), this->members_.m_start), this->members_.m_finish); + else { + const_iterator mid = x.begin() + difference_type(len); + std::copy(x.begin(), mid, this->members_.m_start); + this->insert(this->members_.m_finish, mid, x.end()); + } + } + return *this; + } + + //! Effects: Move assignment. All mx's values are transferred to *this. + //! + //! Postcondition: x.empty(). *this contains a the elements x had + //! before the function. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Linear. + deque& operator= (BOOST_RV_REF(deque) x) + { + this->clear(); + this->swap(x); + return *this; + } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() + //! allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(deque &x) + { + std::swap(this->members_.m_start, x.members_.m_start); + std::swap(this->members_.m_finish, x.members_.m_finish); + std::swap(this->members_.m_map, x.members_.m_map); + std::swap(this->members_.m_map_size, x.members_.m_map_size); + } + + //! Effects: Assigns the n copies of val to *this. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void assign(size_type n, const T& val) + { this->priv_fill_assign(n, val); } + + //! Effects: Assigns the the range [first, last) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! Complexity: Linear to n. + template + void assign(InpIt first, InpIt last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_assign_dispatch(first, last, Result()); + } + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Effects: Inserts a copy of x at the end of the deque. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_back(const T &x); + + //! Effects: Constructs a new element in the end of the deque + //! and moves the resources of mx to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: 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) + //! Effects: Inserts a copy of x at the front of the deque. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_front(const T &x); + + //! Effects: Constructs a new element in the front of the deque + //! and moves the resources of mx to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + void push_front(T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front) + #endif + + //! Effects: Removes the last element from the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + void pop_back() + { + if (this->members_.m_finish.m_cur != this->members_.m_finish.m_first) { + --this->members_.m_finish.m_cur; + containers_detail::get_pointer(this->members_.m_finish.m_cur)->~value_type(); + } + else + this->priv_pop_back_aux(); + } + + //! Effects: Removes the first element from the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + void pop_front() + { + if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) { + containers_detail::get_pointer(this->members_.m_start.m_cur)->~value_type(); + ++this->members_.m_start.m_cur; + } + else + this->priv_pop_front_aux(); + } + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Insert a copy of x before position. + //! + //! Throws: If memory allocation throws or x's copy constructor throws. + //! + //! Complexity: If position is end(), amortized constant time + //! Linear time otherwise. + iterator insert(const_iterator position, const T &x); + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Insert a new element before position with mx's resources. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: 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 + + //! Requires: pos must be a valid iterator of *this. + //! + //! Effects: Insert n copies of x before pos. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void insert(const_iterator pos, size_type n, const value_type& x) + { this->priv_fill_insert(pos, n, x); } + + //! Requires: pos must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [first, last) range before pos. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws or T's copy constructor throws. + //! + //! Complexity: Linear to std::distance [first, last). + template + void insert(const_iterator pos, InpIt first, InpIt last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_insert_dispatch(pos, first, last, Result()); + } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the end of the deque. + //! + //! Throws: If memory allocation throws or the in-place constructor throws. + //! + //! Complexity: Amortized constant time + template + void emplace_back(Args&&... args) + { + if(this->priv_push_back_simple_available()){ + new(this->priv_push_back_simple_pos())value_type(boost::forward(args)...); + this->priv_push_back_simple_commit(); + } + else{ + typedef containers_detail::advanced_insert_aux_emplace type; + type &&proxy = type(boost::forward(args)...); + this->priv_insert_aux_impl(this->cend(), 1, proxy); + } + } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the beginning of the deque. + //! + //! Throws: If memory allocation throws or the in-place constructor throws. + //! + //! Complexity: Amortized constant time + template + void emplace_front(Args&&... args) + { + if(this->priv_push_front_simple_available()){ + new(this->priv_push_front_simple_pos())value_type(boost::forward(args)...); + this->priv_push_front_simple_commit(); + } + else{ + typedef containers_detail::advanced_insert_aux_emplace type; + type &&proxy = type(boost::forward(args)...); + this->priv_insert_aux_impl(this->cbegin(), 1, proxy); + } + } + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... before position + //! + //! Throws: If memory allocation throws or the in-place constructor throws. + //! + //! Complexity: If position is end(), amortized constant time + //! Linear time otherwise. + template + iterator emplace(const_iterator p, Args&&... args) + { + if(p == this->cbegin()){ + this->emplace_front(boost::forward(args)...); + return this->begin(); + } + else if(p == this->cend()){ + this->emplace_back(boost::forward(args)...); + return (this->end()-1); + } + else{ + size_type n = p - this->cbegin(); + typedef containers_detail::advanced_insert_aux_emplace type; + type &&proxy = type(boost::forward(args)...); + this->priv_insert_aux_impl(p, 1, proxy); + return iterator(this->begin() + n); + } + } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //0 args + void emplace_back() + { + if(priv_push_front_simple_available()){ + new(priv_push_front_simple_pos())value_type(); + priv_push_front_simple_commit(); + } + else{ + containers_detail::advanced_insert_aux_emplace proxy; + priv_insert_aux_impl(cend(), 1, proxy); + } + } + + void emplace_front() + { + if(priv_push_front_simple_available()){ + new(priv_push_front_simple_pos())value_type(); + priv_push_front_simple_commit(); + } + else{ + containers_detail::advanced_insert_aux_emplace proxy; + priv_insert_aux_impl(cbegin(), 1, proxy); + } + } + + iterator emplace(const_iterator p) + { + if(p == cbegin()){ + emplace_front(); + return begin(); + } + else if(p == cend()){ + emplace_back(); + return (end()-1); + } + else{ + size_type n = p - cbegin(); + containers_detail::advanced_insert_aux_emplace proxy; + priv_insert_aux_impl(p, 1, proxy); + return iterator(this->begin() + n); + } + } + + //advanced_insert_int.hpp includes all necessary preprocessor machinery... + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + if(priv_push_back_simple_available()){ \ + new(priv_push_back_simple_pos())value_type \ + (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + priv_push_back_simple_commit(); \ + } \ + else{ \ + containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ + \ + proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + priv_insert_aux_impl(cend(), 1, proxy); \ + } \ + } \ + \ + template \ + void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + if(priv_push_front_simple_available()){ \ + new(priv_push_front_simple_pos())value_type \ + (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + priv_push_front_simple_commit(); \ + } \ + else{ \ + containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ + \ + proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + priv_insert_aux_impl(cbegin(), 1, proxy); \ + } \ + } \ + \ + template \ + iterator emplace(const_iterator p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + if(p == this->cbegin()){ \ + this->emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + return this->begin(); \ + } \ + else if(p == cend()){ \ + this->emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + return (this->end()-1); \ + } \ + else{ \ + size_type pos_num = p - this->cbegin(); \ + containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ + \ + proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + this->priv_insert_aux_impl(p, 1, proxy); \ + return iterator(this->begin() + pos_num); \ + } \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size, const value_type& x) + { + const size_type len = size(); + if (new_size < len) + this->erase(this->members_.m_start + new_size, this->members_.m_finish); + else + this->insert(this->members_.m_finish, new_size - len, x); + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default constructed. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size) + { + const size_type len = size(); + if (new_size < len) + this->erase(this->members_.m_start + new_size, this->members_.m_finish); + else{ + size_type n = new_size - this->size(); + containers_detail::default_construct_aux_proxy proxy(n); + priv_insert_aux_impl(this->cend(), n, proxy); + } + } + + //! Effects: Erases the element at position pos. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements between pos and the + //! last element (if pos is near the end) or the first element + //! if(pos is near the beginning). + //! Constant if pos is the first or the last element. + iterator erase(const_iterator pos) + { + const_iterator next = pos; + ++next; + difference_type index = pos - this->members_.m_start; + if (size_type(index) < (this->size() >> 1)) { + boost::move_backward(begin(), iterator(pos), iterator(next)); + pop_front(); + } + else { + boost::move(iterator(next), end(), iterator(pos)); + pop_back(); + } + return this->members_.m_start + index; + } + + //! Effects: Erases the elements pointed by [first, last). + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the distance between first and + //! last plus the elements between pos and the + //! last element (if pos is near the end) or the first element + //! if(pos is near the beginning). + iterator erase(const_iterator first, const_iterator last) + { + if (first == this->members_.m_start && last == this->members_.m_finish) { + this->clear(); + 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(this->size() - n) - elems_before) { + boost::move_backward(begin(), iterator(first), iterator(last)); + 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); + this->priv_destroy_nodes(this->members_.m_start.m_node, new_start.m_node); + this->members_.m_start = new_start; + } + else { + boost::move(iterator(last), end(), iterator(first)); + 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; + } + return this->members_.m_start + elems_before; + } + } + + //! Effects: Erases all the elements of the deque. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the deque. + void clear() + { + for (index_pointer node = this->members_.m_start.m_node + 1; + node < this->members_.m_finish.m_node; + ++node) { + this->priv_destroy_range(*node, *node + this->s_buffer_size()); + this->priv_deallocate_node(*node); + } + + if (this->members_.m_start.m_node != this->members_.m_finish.m_node) { + this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_start.m_last); + this->priv_destroy_range(this->members_.m_finish.m_first, this->members_.m_finish.m_cur); + this->priv_deallocate_node(this->members_.m_finish.m_first); + } + else + this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_finish.m_cur); + + this->members_.m_finish = this->members_.m_start; + } + + //! Effects: Tries to deallocate the excess of memory created + //! with previous allocations. The size of the deque is unchanged + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: 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(); + } + } + + /// @cond + 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) + { + if (position == cbegin()){ + this->push_front(x); + return begin(); + } + else if (position == cend()){ + this->push_back(x); + return (end()-1); + } + else { + size_type n = position - cbegin(); + this->priv_insert_aux(position, size_type(1), x); + return iterator(this->begin() + n); + } + } + + iterator priv_insert(const_iterator position, BOOST_RV_REF(value_type) mx) + { + if (position == cbegin()) { + this->push_front(boost::move(mx)); + return begin(); + } + else if (position == cend()) { + this->push_back(boost::move(mx)); + return(end()-1); + } + 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()){ + new(this->priv_push_front_simple_pos())value_type(t); + this->priv_push_front_simple_commit(); + } + else{ + this->priv_insert_aux(cbegin(), size_type(1), t); + } + } + + void priv_push_front(BOOST_RV_REF(value_type) t) + { + if(this->priv_push_front_simple_available()){ + new(this->priv_push_front_simple_pos())value_type(boost::move(t)); + this->priv_push_front_simple_commit(); + } + else{ + this->priv_insert_aux(cbegin(), move_it(r_iterator(t, 1)), move_it(r_iterator())); + } + } + + void priv_push_back(const value_type &t) + { + if(this->priv_push_back_simple_available()){ + new(this->priv_push_back_simple_pos())value_type(t); + 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()){ + new(this->priv_push_back_simple_pos())value_type(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())); + } + } + + bool priv_push_back_simple_available() const + { + return this->members_.m_map && + (this->members_.m_finish.m_cur != (this->members_.m_finish.m_last - 1)); + } + + void *priv_push_back_simple_pos() const + { + return static_cast(containers_detail::get_pointer(this->members_.m_finish.m_cur)); + } + + void priv_push_back_simple_commit() + { + ++this->members_.m_finish.m_cur; + } + + bool priv_push_front_simple_available() const + { + return this->members_.m_map && + (this->members_.m_start.m_cur != this->members_.m_start.m_first); + } + + void *priv_push_front_simple_pos() const + { return static_cast(containers_detail::get_pointer(this->members_.m_start.m_cur) - 1); } + + void priv_push_front_simple_commit() + { --this->members_.m_start.m_cur; } + + template + 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 + 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 + void priv_initialize_dispatch(Integer n, Integer x, containers_detail::true_) + { + this->priv_initialize_map(n); + this->priv_fill_initialize(x); + } + + template + void priv_initialize_dispatch(InpIt first, InpIt last, containers_detail::false_) + { + typedef typename std::iterator_traits::iterator_category ItCat; + this->priv_range_initialize(first, last, ItCat()); + } + + void priv_destroy_range(iterator p, iterator p2) + { + for(;p != p2; ++p) + containers_detail::get_pointer(&*p)->~value_type(); + } + + void priv_destroy_range(pointer p, pointer p2) + { + for(;p != p2; ++p) + containers_detail::get_pointer(&*p)->~value_type(); + } + + template + void priv_assign_dispatch(Integer n, Integer val, containers_detail::true_) + { this->priv_fill_assign((size_type) n, (value_type)val); } + + template + void priv_assign_dispatch(InpIt first, InpIt last, containers_detail::false_) + { + typedef typename std::iterator_traits::iterator_category ItCat; + this->priv_assign_aux(first, last, ItCat()); + } + + template + 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 + 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()); + std::copy(first, mid, begin()); + this->insert(cend(), mid, last); + } + else + this->erase(std::copy(first, last, begin()), cend()); + } + + template + void priv_insert_dispatch(const_iterator pos, Integer n, Integer x, containers_detail::true_) + { this->priv_fill_insert(pos, (size_type) n, (value_type)x); } + + template + void priv_insert_dispatch(const_iterator pos,InpIt first, InpIt last, containers_detail::false_) + { + typedef typename std::iterator_traits::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 c_it; + this->priv_insert_aux(pos, c_it(x, n), c_it()); + } + + //Just forward all operations to priv_insert_aux_impl + template + void priv_insert_aux(const_iterator p, FwdIt first, FwdIt last) + { + containers_detail::advanced_insert_aux_proxy proxy(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); + 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(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::uninitialized_move(this->members_.m_start, start_n, new_start); + this->members_.m_start = new_start; + boost::move(start_n, pos, old_start); + interf.copy_all_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::uninitialized_move(old_start, pos, new_start); + this->members_.m_start = new_start; + interf.copy_all_to(old_start); + } + } + 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::uninitialized_move(finish_n, this->members_.m_finish, this->members_.m_finish); + this->members_.m_finish = new_finish; + boost::move_backward(pos, finish_n, old_finish); + interf.copy_all_to(pos); + } + else { + interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false); + this->members_.m_finish += n-elemsafter; + ::boost::uninitialized_move(pos, old_finish, this->members_.m_finish); + this->members_.m_finish = new_finish; + interf.copy_all_to(pos); + } + } + } + + void priv_fill_insert(const_iterator pos, size_type n, const value_type& x) + { + typedef constant_iterator c_it; + this->insert(pos, c_it(x, n), c_it()); + } + + // Precondition: this->members_.m_start and this->members_.m_finish have already been initialized, + // but none of the deque's elements have yet been constructed. + void priv_fill_initialize(const value_type& value) + { + index_pointer cur; + BOOST_TRY { + for (cur = this->members_.m_start.m_node; cur < this->members_.m_finish.m_node; ++cur){ + std::uninitialized_fill(*cur, *cur + this->s_buffer_size(), value); + } + std::uninitialized_fill(this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value); + } + BOOST_CATCH(...){ + this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template + void priv_range_initialize(InpIt first, InpIt last, std::input_iterator_tag) + { + this->priv_initialize_map(0); + BOOST_TRY { + for ( ; first != last; ++first) + this->push_back(*first); + } + BOOST_CATCH(...){ + this->clear(); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template + void priv_range_initialize(FwdIt first, FwdIt last, std::forward_iterator_tag) + { + size_type n = 0; + n = std::distance(first, last); + this->priv_initialize_map(n); + + index_pointer cur_node; + BOOST_TRY { + for (cur_node = this->members_.m_start.m_node; + cur_node < this->members_.m_finish.m_node; + ++cur_node) { + FwdIt mid = first; + std::advance(mid, this->s_buffer_size()); + ::boost::uninitialized_copy_or_move(first, mid, *cur_node); + first = mid; + } + ::boost::uninitialized_copy_or_move(first, last, this->members_.m_finish.m_first); + } + BOOST_CATCH(...){ + this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first. + void priv_pop_back_aux() + { + this->priv_deallocate_node(this->members_.m_finish.m_first); + this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1); + this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1; + containers_detail::get_pointer(this->members_.m_finish.m_cur)->~value_type(); + } + + // Called only if this->members_.m_start.m_cur == this->members_.m_start.m_last - 1. Note that + // if the deque has at least one element (a precondition for this member + // function), and if this->members_.m_start.m_cur == this->members_.m_start.m_last, then the deque + // must have at least two nodes. + void priv_pop_front_aux() + { + containers_detail::get_pointer(this->members_.m_start.m_cur)->~value_type(); + this->priv_deallocate_node(this->members_.m_start.m_first); + this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1); + this->members_.m_start.m_cur = this->members_.m_start.m_first; + } + + iterator priv_reserve_elements_at_front(size_type n) + { + size_type vacancies = this->members_.m_start.m_cur - this->members_.m_start.m_first; + if (n > vacancies){ + size_type new_elems = n-vacancies; + size_type new_nodes = (new_elems + this->s_buffer_size() - 1) / + this->s_buffer_size(); + size_type s = (size_type)(this->members_.m_start.m_node - this->members_.m_map); + if (new_nodes > s){ + this->priv_reallocate_map(new_nodes, true); + } + size_type i = 1; + BOOST_TRY { + for (; i <= new_nodes; ++i) + *(this->members_.m_start.m_node - i) = this->priv_allocate_node(); + } + BOOST_CATCH(...) { + for (size_type j = 1; j < i; ++j) + this->priv_deallocate_node(*(this->members_.m_start.m_node - j)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + return this->members_.m_start - difference_type(n); + } + + iterator priv_reserve_elements_at_back(size_type n) + { + size_type vacancies = (this->members_.m_finish.m_last - this->members_.m_finish.m_cur) - 1; + if (n > vacancies){ + size_type new_elems = n - vacancies; + size_type new_nodes = (new_elems + this->s_buffer_size() - 1)/s_buffer_size(); + size_type s = (size_type)(this->members_.m_map_size - (this->members_.m_finish.m_node - this->members_.m_map)); + if (new_nodes + 1 > s){ + this->priv_reallocate_map(new_nodes, false); + } + size_type i; + BOOST_TRY { + for (i = 1; i <= new_nodes; ++i) + *(this->members_.m_finish.m_node + i) = this->priv_allocate_node(); + } + BOOST_CATCH(...) { + for (size_type j = 1; j < i; ++j) + this->priv_deallocate_node(*(this->members_.m_finish.m_node + j)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + return this->members_.m_finish + difference_type(n); + } + + void priv_reallocate_map(size_type nodes_to_add, bool add_at_front) + { + size_type old_num_nodes = this->members_.m_finish.m_node - this->members_.m_start.m_node + 1; + size_type new_num_nodes = old_num_nodes + nodes_to_add; + + index_pointer new_nstart; + if (this->members_.m_map_size > 2 * new_num_nodes) { + new_nstart = this->members_.m_map + (this->members_.m_map_size - new_num_nodes) / 2 + + (add_at_front ? nodes_to_add : 0); + if (new_nstart < this->members_.m_start.m_node) + boost::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); + else + boost::move_backward + (this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart + old_num_nodes); + } + else { + size_type new_map_size = + this->members_.m_map_size + containers_detail::max_value(this->members_.m_map_size, nodes_to_add) + 2; + + index_pointer new_map = this->priv_allocate_map(new_map_size); + new_nstart = new_map + (new_map_size - new_num_nodes) / 2 + + (add_at_front ? nodes_to_add : 0); + boost::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); + this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); + + this->members_.m_map = new_map; + this->members_.m_map_size = new_map_size; + } + + this->members_.m_start.priv_set_node(new_nstart); + this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1); + } + /// @endcond +}; + +// Nonmember functions. +template +inline bool operator==(const deque& x, + const deque& y) +{ + return x.size() == y.size() && equal(x.begin(), x.end(), y.begin()); +} + +template +inline bool operator<(const deque& x, + const deque& y) +{ + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); +} + +template +inline bool operator!=(const deque& x, + const deque& y) + { return !(x == y); } + +template +inline bool operator>(const deque& x, + const deque& y) + { return y < x; } + +template +inline bool operator<=(const deque& x, + const deque& y) + { return !(y < x); } + +template +inline bool operator>=(const deque& x, + const deque& y) + { return !(x < y); } + + +template +inline void swap(deque& x, deque& y) +{ x.swap(y); } + +}} + +/// @cond + +namespace boost { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = has_trivial_destructor::value }; +}; +*/ +} + +/// @endcond + +#include + +#endif // #ifndef BOOST_CONTAINERS_DEQUE_HPP diff --git a/include/boost/container/detail/adaptive_node_pool_impl.hpp b/include/boost/container/detail/adaptive_node_pool_impl.hpp new file mode 100644 index 0000000..d462ee3 --- /dev/null +++ b/include/boost/container/detail/adaptive_node_pool_impl.hpp @@ -0,0 +1,648 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP +#define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace container { +namespace containers_detail { + +template +struct hdr_offset_holder_t +{ + hdr_offset_holder_t(size_type offset = 0) + : hdr_offset(offset) + {} + size_type hdr_offset; +}; + +template +struct adaptive_pool_types +{ + typedef VoidPointer void_pointer; + typedef typename bi::make_set_base_hook + < bi::void_pointer + , bi::optimize_size + , bi::constant_time_size + , bi::link_mode >::type multiset_hook_t; + + typedef hdr_offset_holder_t hdr_offset_holder; + + struct block_info_t + : + public hdr_offset_holder, + public multiset_hook_t + { + typedef typename node_slist::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)); + } + + friend bool operator ==(const block_info_t &l, const block_info_t &r) + { return &l == &r; } + }; + typedef typename bi::make_multiset + >::type block_multiset_t; +}; + +template +inline size_type calculate_alignment + ( size_type overhead_percent, size_type real_node_size + , size_type hdr_size, size_type hdr_offset_size, size_type payload_per_allocation) +{ + //to-do: handle real_node_size != node_size + const size_type divisor = overhead_percent*real_node_size; + const size_type dividend = hdr_offset_size*100; + size_type elements_per_subblock = (dividend - 1)/divisor + 1; + size_type candidate_power_of_2 = + upper_power_of_2(elements_per_subblock*real_node_size + hdr_offset_size); + bool overhead_satisfied = false; + //Now calculate the wors-case overhead for a subblock + const size_type max_subblock_overhead = hdr_size + payload_per_allocation; + while(!overhead_satisfied){ + elements_per_subblock = (candidate_power_of_2 - max_subblock_overhead)/real_node_size; + const size_type overhead_size = candidate_power_of_2 - elements_per_subblock*real_node_size; + if(overhead_size*100/candidate_power_of_2 < overhead_percent){ + overhead_satisfied = true; + } + else{ + candidate_power_of_2 <<= 1; + } + } + return candidate_power_of_2; +} + +template +inline void calculate_num_subblocks + (size_type alignment, size_type real_node_size, size_type elements_per_block + , 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) +{ + 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; + } + elements_per_subblock = (alignment - hdr_offset_size)/real_node_size; + bool overhead_satisfied = false; + while(!overhead_satisfied){ + const size_type total_data = (elements_per_subblock*(possible_num_subblock-1) + hdr_subblock_elements)*real_node_size; + const size_type total_size = alignment*possible_num_subblock; + if((total_size - total_data)*100/total_size < overhead_percent){ + overhead_satisfied = true; + } + else{ + ++possible_num_subblock; + } + } + num_subblocks = possible_num_subblock; + real_num_node = (possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements; +} + +template +class private_adaptive_node_pool_impl +{ + //Non-copyable + private_adaptive_node_pool_impl(); + private_adaptive_node_pool_impl(const private_adaptive_node_pool_impl &); + private_adaptive_node_pool_impl &operator=(const private_adaptive_node_pool_impl &); + typedef private_adaptive_node_pool_impl this_type; + + typedef typename SegmentManagerBase::void_pointer void_pointer; + static const typename SegmentManagerBase:: + size_type PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation; + typedef bool_ IsAlignOnly; + typedef true_ AlignOnlyTrue; + typedef false_ AlignOnlyFalse; + + public: + typedef typename node_slist::node_t node_t; + typedef typename node_slist::node_slist_t free_nodes_t; + typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain; + typedef typename SegmentManagerBase::size_type size_type; + + private: + typedef typename adaptive_pool_types::block_info_t block_info_t; + typedef typename adaptive_pool_types::block_multiset_t block_multiset_t; + typedef typename block_multiset_t::iterator block_iterator; + typedef typename adaptive_pool_types::hdr_offset_holder hdr_offset_holder; + + static const size_type MaxAlign = alignment_of::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; + + //!Constructor from a segment manager. Never throws + private_adaptive_node_pool_impl + ( segment_manager_base_type *segment_mngr_base + , size_type node_size + , size_type nodes_per_block + , size_type max_free_blocks + , unsigned char overhead_percent + ) + : m_max_free_blocks(max_free_blocks) + , m_real_node_size(lcm(node_size, size_type(alignment_of::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 + , m_real_block_alignment + (AlignOnly ? + upper_power_of_2(HdrSize + m_real_node_size*nodes_per_block) : + calculate_alignment( (size_type)overhead_percent, m_real_node_size + , HdrSize, HdrOffsetSize, PayloadPerAllocation)) + //This is the real number of nodes per block + , m_num_subblocks(0) + , 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_totally_free_blocks(0) + { + if(!AlignOnly){ + calculate_num_subblocks + ( m_real_block_alignment + , m_real_node_size + , nodes_per_block + , m_num_subblocks + , m_real_num_node + , (size_type)overhead_percent + , HdrSize + , HdrOffsetSize + , PayloadPerAllocation); + } + } + + //!Destructor. Deallocates all allocated blocks. Never throws + ~private_adaptive_node_pool_impl() + { priv_clear(); } + + size_type get_real_num_node() const + { return m_real_num_node; } + + //!Returns the segment manager. Never throws + segment_manager_base_type* get_segment_manager_base()const + { return containers_detail::get_pointer(mp_segment_mngr_base); } + + //!Allocates array of count elements. Can throw + void *allocate_node() + { + priv_invariants(); + //If there are no free nodes we allocate a new block + if (m_block_multiset.empty()){ + priv_alloc_block(1); + } + //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(); + } + + //!Allocates n nodes. + //!Can throw + multiallocation_chain allocate_nodes(const size_type n) + { + multiallocation_chain chain; + size_type i = 0; + try{ + 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); + } + free_nodes_t &free_nodes = m_block_multiset.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); + } + + if(free_nodes.empty()){ + m_block_multiset.erase(m_block_multiset.begin()); + } + i += num_elems; + } + } + catch(...){ + this->deallocate_nodes(boost::move(chain)); + throw; + } + priv_invariants(); + return boost::move(chain); + } + + //!Deallocates a linked list of nodes. Never throws + 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_deallocate_free_blocks(m_max_free_blocks); + } + } + + void deallocate_free_blocks() + { this->priv_deallocate_free_blocks(0); } + + size_type num_free_nodes() + { + typedef typename block_multiset_t::const_iterator citerator; + size_type count = 0; + citerator it (m_block_multiset.begin()), itend(m_block_multiset.end()); + for(; it != itend; ++it){ + count += it->free_nodes.size(); + } + return count; + } + + void swap(private_adaptive_node_pool_impl &other) + { + BOOST_ASSERT(m_max_free_blocks == other.m_max_free_blocks); + BOOST_ASSERT(m_real_node_size == other.m_real_node_size); + BOOST_ASSERT(m_real_block_alignment == other.m_real_block_alignment); + 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); + } + + //Deprecated, use deallocate_free_blocks + void deallocate_free_chunks() + { this->priv_deallocate_free_blocks(0); } + + private: + void priv_deallocate_free_blocks(size_type max_free_blocks) + { + 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; + --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 = containers_detail::get_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(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); + } + 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(); + } + } + + node_t *priv_take_first_node() + { + 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()); + } + else if(free_nodes_count == m_real_num_node){ + --m_totally_free_blocks; + } + priv_invariants(); + return first_node; + } + + class block_destroyer; + friend class block_destroyer; + + class block_destroyer + { + public: + block_destroyer(const this_type *impl) + : mp_impl(impl) + {} + + void operator()(typename block_multiset_t::pointer to_deallocate) + { return this->do_destroy(to_deallocate, IsAlignOnly()); } + + private: + void do_destroy(typename block_multiset_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); + } + + void do_destroy(typename block_multiset_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(0 == to_deallocate->hdr_offset); + hdr_offset_holder *hdr_off_holder = mp_impl->priv_first_subblock_from_block(containers_detail::get_pointer(to_deallocate)); + mp_impl->mp_segment_mngr_base->deallocate(hdr_off_holder); + } + + const this_type *mp_impl; + }; + + //This macro will activate invariant checking. Slow, but helpful for debugging the code. + //#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS + void priv_invariants() + #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; + } + } + //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(); + } + 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; + } + BOOST_ASSERT(total_free >= m_totally_free_blocks); + + if(!AlignOnly){ + //Check that header offsets are correct + it = m_block_multiset.begin(); + for(; it != itend; ++it){ + hdr_offset_holder *hdr_off_holder = priv_first_subblock_from_block(&*it); + for(size_type i = 0, max = m_num_subblocks; i < max; ++i){ + BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast(&*it)- reinterpret_cast(hdr_off_holder))); + 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(reinterpret_cast(hdr_off_holder) + m_real_block_alignment); + } + } + } + } + #else + {} //empty + #endif + + //!Deallocates all used memory. Never throws + 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; + for(; it != itend; ++it){ + //Check for memory leak + BOOST_ASSERT(it->free_nodes.size() == m_real_num_node); + ++num_free_nodes; + } + BOOST_ASSERT(num_free_nodes == m_totally_free_blocks); + #endif + //Check for memory leaks + priv_invariants(); + m_block_multiset.clear_and_dispose(block_destroyer(this)); + m_totally_free_blocks = 0; + } + + block_info_t *priv_block_from_node(void *node, AlignOnlyFalse) const + { + hdr_offset_holder *hdr_off_holder = + reinterpret_cast((std::size_t)node & size_type(~(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))); + block_info_t *block = reinterpret_cast + (reinterpret_cast(hdr_off_holder) + hdr_off_holder->hdr_offset); + BOOST_ASSERT(block->hdr_offset == 0); + return block; + } + + block_info_t *priv_block_from_node(void *node, AlignOnlyTrue) const + { + return (block_info_t *)((std::size_t)node & std::size_t(~(m_real_block_alignment - 1))); + } + + block_info_t *priv_block_from_node(void *node) const + { return priv_block_from_node(node, IsAlignOnly()); } + + hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block) const + { + hdr_offset_holder *hdr_off_holder = reinterpret_cast + (reinterpret_cast(block) - (m_num_subblocks-1)*m_real_block_alignment); + BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast(block) - reinterpret_cast(hdr_off_holder))); + 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; + } + + //!Allocates a several blocks of nodes. Can throw + void priv_alloc_block(size_type n, AlignOnlyTrue) + { + size_type real_block_size = m_real_block_alignment - PayloadPerAllocation; + 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 + (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); + + 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; + } + } + } + + void priv_alloc_block(size_type n, 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; + + 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 + (mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment)); + if(!mem_address) throw std::bad_alloc(); + ++m_totally_free_blocks; + + //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; + //Some structural checks + BOOST_ASSERT(static_cast(&static_cast(c_info)->hdr_offset) == + static_cast(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; + } + } + { + 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; + } + } + //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::pointer_to_other + ::type segment_mngr_base_ptr_t; + const size_type m_max_free_blocks; + const size_type m_real_node_size; + //Round the size to a power of two value. + //This is the total memory size (including payload) that we want to + //allocate from the general-purpose allocator + const size_type m_real_block_alignment; + size_type m_num_subblocks; + //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 +}; + +} //namespace containers_detail { +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP diff --git a/include/boost/container/detail/advanced_insert_int.hpp b/include/boost/container/detail/advanced_insert_int.hpp new file mode 100644 index 0000000..77f3547 --- /dev/null +++ b/include/boost/container/detail/advanced_insert_int.hpp @@ -0,0 +1,385 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-2011. 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_CONTAINERS_ADVANCED_INSERT_INT_HPP +#define BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include +#include +#include //std::iterator_traits +#include //placement new +#include + +namespace boost { namespace container { namespace containers_detail { + +//This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl +template +struct advanced_insert_aux_int +{ + typedef typename std::iterator_traits::difference_type difference_type; + virtual void copy_all_to(Iterator p) = 0; + virtual void uninitialized_copy_all_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() {} +}; + +//This class template will adapt each FwIt types to advanced_insert_aux_int +template +struct advanced_insert_aux_proxy + : public advanced_insert_aux_int +{ + typedef typename advanced_insert_aux_int::difference_type difference_type; + advanced_insert_aux_proxy(FwdIt first, FwdIt last) + : first_(first), last_(last) + {} + + virtual ~advanced_insert_aux_proxy() + {} + + virtual void copy_all_to(Iterator p) + { ::boost::copy_or_move(first_, last_, p); } + + virtual void uninitialized_copy_all_to(Iterator p) + { ::boost::uninitialized_copy_or_move(first_, last_, p); } + + virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) + { + FwdIt mid = first_; + std::advance(mid, division_count); + if(first_n){ + ::boost::uninitialized_copy_or_move(first_, mid, pos); + first_ = mid; + } + else{ + ::boost::uninitialized_copy_or_move(mid, last_, pos); + last_ = mid; + } + } + + virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) + { + FwdIt mid = first_; + std::advance(mid, division_count); + if(first_n){ + ::boost::copy_or_move(first_, mid, pos); + first_ = mid; + } + else{ + ::boost::copy_or_move(mid, last_, pos); + last_ = mid; + } + } + + FwdIt first_, last_; +}; + +//This class template will adapt each FwIt types to advanced_insert_aux_int +template +struct default_construct_aux_proxy + : public advanced_insert_aux_int +{ + typedef typename advanced_insert_aux_int::difference_type difference_type; + default_construct_aux_proxy(SizeType count) + : count_(count) + {} + + void uninitialized_copy_impl(Iterator p, const SizeType n) + { + BOOST_ASSERT(n <= count_); + Iterator orig_p = p; + SizeType i = 0; + try{ + for(; i < n; ++i, ++p){ + new(containers_detail::get_pointer(&*p))T(); + } + } + catch(...){ + while(i--){ + containers_detail::get_pointer(&*orig_p++)->~T(); + } + throw; + } + count_ -= n; + } + + virtual ~default_construct_aux_proxy() + {} + + virtual void copy_all_to(Iterator) + { //This should never be called with any count + BOOST_ASSERT(count_ == 0); + } + + virtual void uninitialized_copy_all_to(Iterator p) + { this->uninitialized_copy_impl(p, count_); } + + virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) + { + SizeType new_count; + if(first_n){ + new_count = division_count; + } + else{ + BOOST_ASSERT(difference_type(count_)>= division_count); + new_count = count_ - division_count; + } + this->uninitialized_copy_impl(pos, new_count); + } + + virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n) + { + BOOST_ASSERT(count_ == 0); + SizeType new_count; + if(first_n){ + new_count = division_count; + } + else{ + BOOST_ASSERT(difference_type(count_)>= division_count); + new_count = count_ - division_count; + } + //This function should never called with a count different to zero + BOOST_ASSERT(new_count == 0); + (void)new_count; + } + + SizeType count_; +}; + +}}} //namespace boost { namespace container { namespace containers_detail { + +#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + +#include +#include +#include +#include +//#include //For debugging purposes + +namespace boost { +namespace container { +namespace containers_detail { + +//This class template will adapt each FwIt types to advanced_insert_aux_int +template +struct advanced_insert_aux_emplace + : public advanced_insert_aux_int +{ + typedef typename advanced_insert_aux_int::difference_type difference_type; + typedef typename build_number_seq::type index_tuple_t; + + explicit advanced_insert_aux_emplace(Args&&... args) + : args_(args...) + , used_(false) + {} + + ~advanced_insert_aux_emplace() + {} + + virtual void copy_all_to(Iterator p) + { this->priv_copy_all_to(index_tuple_t(), p); } + + virtual void uninitialized_copy_all_to(Iterator p) + { this->priv_uninitialized_copy_all_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 p, difference_type division_count, bool first_n) + { this->priv_copy_some_and_update(index_tuple_t(), p, division_count, first_n); } + + private: + template + void priv_copy_all_to(const index_tuple&, Iterator p) + { + if(!used_){ + *p = boost::move(T (::boost::container::containers_detail::stored_ref::forward(get(args_))...)); + used_ = true; + } + } + + template + void priv_uninitialized_copy_all_to(const index_tuple&, Iterator p) + { + if(!used_){ + new(containers_detail::get_pointer(&*p))T(::boost::container::containers_detail::stored_ref::forward(get(args_))...); + used_ = true; + } + } + + template + void priv_uninitialized_copy_some_and_update(const index_tuple&, 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(!used_){ + new(containers_detail::get_pointer(&*p))T(::boost::container::containers_detail::stored_ref::forward(get(args_))...); + used_ = true; + } + } + } + + template + void priv_copy_some_and_update(const index_tuple&, 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(!used_){ + *p = boost::move(T(::boost::container::containers_detail::stored_ref::forward(get(args_))...)); + used_ = true; + } + } + } + tuple args_; + bool used_; +}; + +}}} //namespace boost { namespace container { namespace containers_detail { + +#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + +#include +#include + +namespace boost { +namespace container { +namespace containers_detail { + +//This class template will adapt each FwIt types to advanced_insert_aux_int +template +struct advanced_insert_aux_emplace + : public advanced_insert_aux_int +{ + typedef typename advanced_insert_aux_int::difference_type difference_type; + advanced_insert_aux_emplace() + : used_(false) + {} + + ~advanced_insert_aux_emplace() + {} + + virtual void copy_all_to(Iterator p) + { + if(!used_){ + value_initv; + *p = boost::move(v.m_t); + used_ = true; + } + } + + virtual void uninitialized_copy_all_to(Iterator p) + { + if(!used_){ + new(containers_detail::get_pointer(&*p))T(); + used_ = true; + } + } + + 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(!used_){ + new(containers_detail::get_pointer(&*p))T(); + used_ = true; + } + } + } + + 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(!used_){ + value_initv; + *p = boost::move(v.m_t); + used_ = true; + } + } + } + private: + bool used_; +}; + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ + : public advanced_insert_aux_int \ + { \ + typedef typename advanced_insert_aux_int::difference_type difference_type; \ + \ + BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ + ( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) ) \ + : used_(false), BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {} \ + \ + virtual void copy_all_to(Iterator p) \ + { \ + if(!used_){ \ + T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \ + *p = boost::move(v); \ + used_ = true; \ + } \ + } \ + \ + virtual void uninitialized_copy_all_to(Iterator p) \ + { \ + if(!used_){ \ + new(containers_detail::get_pointer(&*p))T \ + (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \ + used_ = true; \ + } \ + } \ + \ + 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(!used_){ \ + new(containers_detail::get_pointer(&*p))T \ + (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \ + used_ = true; \ + } \ + } \ + } \ + \ + 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(!used_){ \ + T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \ + *p = boost::move(v); \ + used_ = true; \ + } \ + } \ + } \ + \ + bool used_; \ + BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _) \ + }; \ +//! + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) +#include BOOST_PP_LOCAL_ITERATE() + +}}} //namespace boost { namespace container { namespace containers_detail { + +#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + +#include + +#endif //#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP diff --git a/include/boost/container/detail/algorithms.hpp b/include/boost/container/detail/algorithms.hpp new file mode 100644 index 0000000..677bebe --- /dev/null +++ b/include/boost/container/detail/algorithms.hpp @@ -0,0 +1,215 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. +// +// 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_CONTAINERS_DETAIL_ALGORITHMS_HPP +#define BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include + +#include +#include +#include +#include + +#include +#include +#include + + +#include + +namespace boost { +namespace container { + +#if defined(BOOST_NO_RVALUE_REFERENCES) +template +struct has_own_construct_from_it +{ + static const bool value = false; +}; + +namespace containers_detail { + +template +inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::true_) +{ + T::construct(dest, *source); +} + +template +inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::false_) +{ + new((void*)dest)T(*source); +} + +} //namespace containers_detail { + +template +inline void construct_in_place(T* dest, InpIt source) +{ + typedef containers_detail::bool_::value> boolean_t; + containers_detail::construct_in_place_impl(dest, source, boolean_t()); +} + +#else +template +inline void construct_in_place(T* dest, InpIt source) +{ ::new((void*)dest)T(*source); } +#endif + +template +inline void construct_in_place(T *dest, default_construct_iterator) +{ + ::new((void*)dest)T(); +} + +template +inline void construct_in_place(T *dest, emplace_iterator ei) +{ + ei.construct_in_place(dest); +} + +template +struct optimize_assign +{ + static const bool value = false; +}; + +template +struct optimize_assign +{ + static const bool value = boost::has_trivial_assign::value; +}; + +template +struct optimize_assign + : public optimize_assign +{}; + +template +struct optimize_copy +{ + static const bool value = false; +}; + +template +struct optimize_copy +{ + static const bool value = boost::has_trivial_copy::value; +}; + +template +struct optimize_copy + : public optimize_copy +{}; + +template inline +OutIt copy_n_dispatch(InIt first, typename std::iterator_traits::difference_type length, OutIt dest, containers_detail::bool_) +{ + for (; length--; ++dest, ++first) + *dest = *first; + return dest; +} + +template inline +T *copy_n_dispatch(const T *first, typename std::iterator_traits::difference_type length, T *dest, containers_detail::bool_) +{ + std::size_t size = length*sizeof(T); + return (static_cast(std::memmove(dest, first, size))) + size; +} + +template inline +OutIt copy_n(InIt first, typename std::iterator_traits::difference_type length, OutIt dest) +{ + const bool do_optimized_assign = optimize_assign::value; + return copy_n_dispatch(first, length, dest, containers_detail::bool_()); +} + +template inline +FwdIt uninitialized_copy_n_dispatch + (InIt first, + typename std::iterator_traits::difference_type count, + FwdIt dest, containers_detail::bool_) +{ + typedef typename std::iterator_traits::value_type value_type; + //Save initial destination position + FwdIt dest_init = dest; + typename std::iterator_traits::difference_type new_count = count+1; + + BOOST_TRY{ + //Try to build objects + for (; --new_count; ++dest, ++first){ + construct_in_place(containers_detail::get_pointer(&*dest), first); + } + } + BOOST_CATCH(...){ + //Call destructors + new_count = count - new_count; + for (; new_count--; ++dest_init){ + containers_detail::get_pointer(&*dest_init)->~value_type(); + } + BOOST_RETHROW + } + BOOST_CATCH_END + return dest; +} +template inline +T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits::difference_type length, T *dest, containers_detail::bool_) +{ + std::size_t size = length*sizeof(T); + return (static_cast(std::memmove(dest, first, size))) + size; +} + +template inline +FwdIt uninitialized_copy_n + (InIt first, + typename std::iterator_traits::difference_type count, + FwdIt dest) +{ + const bool do_optimized_copy = optimize_copy::value; + return uninitialized_copy_n_dispatch(first, count, dest, containers_detail::bool_()); +} + +// uninitialized_copy_copy +// Copies [first1, last1) into [result, result + (last1 - first1)), and +// copies [first2, last2) into +// [result + (last1 - first1), result + (last1 - first1) + (last2 - first2)). +template +FwdIt uninitialized_copy_copy + (InpIt1 first1, InpIt1 last1, InpIt2 first2, InpIt2 last2, FwdIt result) +{ + typedef typename std::iterator_traits::value_type value_type; + FwdIt mid = std::uninitialized_copy(first1, last1, result); + BOOST_TRY { + return std::uninitialized_copy(first2, last2, mid); + } + BOOST_CATCH(...){ + for(;result != mid; ++result){ + containers_detail::get_pointer(&*result)->~value_type(); + } + BOOST_RETHROW + } + BOOST_CATCH_END +} + +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP + diff --git a/include/boost/container/detail/allocation_type.hpp b/include/boost/container/detail/allocation_type.hpp new file mode 100644 index 0000000..b479cff --- /dev/null +++ b/include/boost/container/detail/allocation_type.hpp @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_ALLOCATION_TYPE_HPP +#define BOOST_CONTAINERS_ALLOCATION_TYPE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include + +namespace boost { +namespace container { + +/// @cond +enum allocation_type_v +{ + // constants for allocation commands + allocate_new_v = 0x01, + expand_fwd_v = 0x02, + expand_bwd_v = 0x04, +// expand_both = expand_fwd | expand_bwd, +// expand_or_new = allocate_new | expand_both, + shrink_in_place_v = 0x08, + nothrow_allocation_v = 0x10, + zero_memory_v = 0x20, + try_shrink_in_place_v = 0x40 +}; + +typedef int allocation_type; +/// @endcond +static const allocation_type allocate_new = (allocation_type)allocate_new_v; +static const allocation_type expand_fwd = (allocation_type)expand_fwd_v; +static const allocation_type expand_bwd = (allocation_type)expand_bwd_v; +static const allocation_type shrink_in_place = (allocation_type)shrink_in_place_v; +static const allocation_type try_shrink_in_place= (allocation_type)try_shrink_in_place_v; +static const allocation_type nothrow_allocation = (allocation_type)nothrow_allocation_v; +static const allocation_type zero_memory = (allocation_type)zero_memory_v; + +} //namespace container { +} //namespace boost { + +#include + +#endif //BOOST_CONTAINERS_ALLOCATION_TYPE_HPP diff --git a/include/boost/container/detail/config_begin.hpp b/include/boost/container/detail/config_begin.hpp new file mode 100644 index 0000000..4be21ff --- /dev/null +++ b/include/boost/container/detail/config_begin.hpp @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED +#define BOOST_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED +#include + +#endif //BOOST_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED + +#ifdef BOOST_MSVC + #ifndef _CRT_SECURE_NO_DEPRECATE + #define BOOST_CONTAINERS_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 + #pragma warning (disable : 4127) // conditional expression is constant + #pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned + #pragma warning (disable : 4284) // odd return type for operator-> + #pragma warning (disable : 4244) // possible loss of data + #pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2" + #pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data + #pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier" + #pragma warning (disable : 4355) // "this" : used in base member initializer list + #pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated + #pragma warning (disable : 4511) // copy constructor could not be generated + #pragma warning (disable : 4512) // assignment operator could not be generated + #pragma warning (disable : 4514) // unreferenced inline removed + #pragma warning (disable : 4521) // Disable "multiple copy constructors specified" + #pragma warning (disable : 4522) // "class" : multiple assignment operators specified + #pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter + #pragma warning (disable : 4710) // function not inlined + #pragma warning (disable : 4711) // function selected for automatic inline expansion + #pragma warning (disable : 4786) // identifier truncated in debug info + #pragma warning (disable : 4996) // "function": was declared deprecated + #pragma warning (disable : 4197) // top-level volatile in cast is ignored + #pragma warning (disable : 4541) // 'typeid' used on polymorphic type 'boost::exception' + // with /GR-; unpredictable behavior may result + #pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site + #pragma warning (disable : 4671) // the copy constructor is inaccessible +#endif //BOOST_MSVC diff --git a/include/boost/container/detail/config_end.hpp b/include/boost/container/detail/config_end.hpp new file mode 100644 index 0000000..4713a66 --- /dev/null +++ b/include/boost/container/detail/config_end.hpp @@ -0,0 +1,17 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#if defined BOOST_MSVC + #pragma warning (pop) + #ifdef BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE + #undef BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE + #undef _CRT_SECURE_NO_DEPRECATE + #endif +#endif + diff --git a/include/boost/container/detail/destroyers.hpp b/include/boost/container/detail/destroyers.hpp new file mode 100644 index 0000000..22fcf76 --- /dev/null +++ b/include/boost/container/detail/destroyers.hpp @@ -0,0 +1,154 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. +// +// 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_CONTAINERS_DESTROYERS_HPP +#define BOOST_CONTAINERS_DESTROYERS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include +#include +#include + +namespace boost { +namespace container { +namespace containers_detail { + +//!A deleter for scoped_ptr that deallocates the memory +//!allocated for an array of objects using a STL allocator. +template +struct scoped_array_deallocator +{ + typedef typename Allocator::pointer pointer; + typedef typename Allocator::size_type size_type; + + scoped_array_deallocator(pointer p, Allocator& a, size_type length) + : m_ptr(p), m_alloc(a), m_length(length) {} + + ~scoped_array_deallocator() + { if (m_ptr) m_alloc.deallocate(m_ptr, m_length); } + + void release() + { m_ptr = 0; } + + private: + pointer m_ptr; + Allocator& m_alloc; + size_type m_length; +}; + +template +struct null_scoped_array_deallocator +{ + typedef typename Allocator::pointer pointer; + typedef typename Allocator::size_type size_type; + + null_scoped_array_deallocator(pointer, Allocator&, size_type) + {} + + void release() + {} +}; + + +//!A deleter for scoped_ptr that destroys +//!an object using a STL allocator. +template +struct scoped_destructor_n +{ + typedef typename Allocator::pointer pointer; + typedef typename Allocator::value_type value_type; + typedef typename Allocator::size_type size_type; + + pointer m_p; + size_type m_n; + + scoped_destructor_n(pointer p, size_type n) + : m_p(p), m_n(n) + {} + + void release() + { m_p = 0; } + + void increment_size(size_type inc) + { m_n += inc; } + + ~scoped_destructor_n() + { + if(!m_p) return; + value_type *raw_ptr = containers_detail::get_pointer(m_p); + for(size_type i = 0; i < m_n; ++i, ++raw_ptr) + raw_ptr->~value_type(); + } +}; + +//!A deleter for scoped_ptr that destroys +//!an object using a STL allocator. +template +struct null_scoped_destructor_n +{ + typedef typename Allocator::pointer pointer; + typedef typename Allocator::size_type size_type; + + null_scoped_destructor_n(pointer, size_type) + {} + + void increment_size(size_type) + {} + + void release() + {} +}; + +template +class allocator_destroyer +{ + typedef typename A::value_type value_type; + typedef containers_detail::integral_constant::value> alloc_version; + typedef containers_detail::integral_constant allocator_v1; + typedef containers_detail::integral_constant allocator_v2; + + private: + A & a_; + + private: + void priv_deallocate(const typename A::pointer &p, allocator_v1) + { a_.deallocate(p, 1); } + + void priv_deallocate(const typename A::pointer &p, allocator_v2) + { a_.deallocate_one(p); } + + public: + allocator_destroyer(A &a) + : a_(a) + {} + + void operator()(const typename A::pointer &p) + { + containers_detail::get_pointer(p)->~value_type(); + priv_deallocate(p, alloc_version()); + } +}; + + +} //namespace containers_detail { +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINERS_DESTROYERS_HPP diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp new file mode 100644 index 0000000..7cbc175 --- /dev/null +++ b/include/boost/container/detail/flat_tree.hpp @@ -0,0 +1,858 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_FLAT_TREE_HPP +#define BOOST_CONTAINERS_FLAT_TREE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { + +namespace container { + +namespace containers_detail { + +template +class flat_tree_value_compare + : private Compare +{ + typedef Value first_argument_type; + typedef Value second_argument_type; + typedef bool return_type; + public: + flat_tree_value_compare(const Compare &pred) + : Compare(pred) + {} + + bool operator()(const Value& lhs, const Value& rhs) const + { + KeyOfValue key_extract; + return Compare::operator()(key_extract(lhs), key_extract(rhs)); + } + + const Compare &get_comp() const + { return *this; } + + Compare &get_comp() + { return *this; } +}; + +template +struct get_flat_tree_iterators +{ + typedef typename containers_detail:: + vector_iterator iterator; + typedef typename containers_detail:: + vector_const_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +}; + +template +class flat_tree +{ + typedef boost::container::vector vector_t; + typedef A allocator_t; + + public: + typedef flat_tree_value_compare value_compare; + + private: + struct Data + //Inherit from value_compare to do EBO + : public value_compare + { + private: + BOOST_COPYABLE_AND_MOVABLE(Data) + public: + Data(const Data &d) + : value_compare(d), m_vect(d.m_vect) + {} + Data(const Compare &comp, + const vector_t &vect) + : value_compare(comp), m_vect(vect){} + + Data(const value_compare &comp, + const vector_t &vect) + : value_compare(comp), m_vect(vect){} + + Data(const Compare &comp, + const allocator_t &alloc) + : value_compare(comp), m_vect(alloc){} + + Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d) + { + this->value_compare::operator=(d); + m_vect = d.m_vect; + return *this; + } + + Data& operator=(BOOST_RV_REF(Data) d) + { + this->value_compare::operator=(boost::move(static_cast(d))); + m_vect = boost::move(d.m_vect); + return *this; + } + + vector_t m_vect; + }; + + Data m_data; + BOOST_COPYABLE_AND_MOVABLE(flat_tree) + + public: + + typedef typename vector_t::value_type value_type; + typedef typename vector_t::pointer pointer; + typedef typename vector_t::const_pointer const_pointer; + typedef typename vector_t::reference reference; + typedef typename vector_t::const_reference const_reference; + typedef Key key_type; + typedef Compare key_compare; + typedef typename vector_t::allocator_type allocator_type; + typedef allocator_type stored_allocator_type; + typedef typename allocator_type::size_type size_type; + typedef typename allocator_type::difference_type difference_type; + typedef typename vector_t::iterator iterator; + typedef typename vector_t::const_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + + // allocation/deallocation + flat_tree(const Compare& comp = Compare(), + const allocator_type& a = allocator_type()) + : m_data(comp, a) + { } + + flat_tree(const flat_tree& x) + : m_data(x.m_data, x.m_data.m_vect) + { } + + flat_tree(BOOST_RV_REF(flat_tree) x) + : m_data(boost::move(x.m_data)) + { } + + template + flat_tree( ordered_range_t, InputIterator first, InputIterator last + , const Compare& comp = Compare() + , const allocator_type& a = allocator_type()) + : m_data(comp, a) + { this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last); } + + ~flat_tree() + { } + + flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x) + { m_data = x.m_data; return *this; } + + flat_tree& operator=(BOOST_RV_REF(flat_tree) mx) + { m_data = boost::move(mx.m_data); return *this; } + + public: + // accessors: + Compare key_comp() const + { return this->m_data.get_comp(); } + + allocator_type get_allocator() const + { return this->m_data.m_vect.get_allocator(); } + + const stored_allocator_type &get_stored_allocator() const + { return this->m_data.m_vect.get_stored_allocator(); } + + stored_allocator_type &get_stored_allocator() + { return this->m_data.m_vect.get_stored_allocator(); } + + iterator begin() + { return this->m_data.m_vect.begin(); } + + const_iterator begin() const + { return this->cbegin(); } + + const_iterator cbegin() const + { return this->m_data.m_vect.begin(); } + + iterator end() + { return this->m_data.m_vect.end(); } + + const_iterator end() const + { return this->cend(); } + + const_iterator cend() const + { return this->m_data.m_vect.end(); } + + reverse_iterator rbegin() + { return reverse_iterator(this->end()); } + + const_reverse_iterator rbegin() const + { return this->crbegin(); } + + const_reverse_iterator crbegin() const + { return const_reverse_iterator(this->cend()); } + + reverse_iterator rend() + { return reverse_iterator(this->begin()); } + + const_reverse_iterator rend() const + { return this->crend(); } + + const_reverse_iterator crend() const + { return const_reverse_iterator(this->cbegin()); } + + bool empty() const + { return this->m_data.m_vect.empty(); } + + size_type size() const + { return this->m_data.m_vect.size(); } + + size_type max_size() const + { return this->m_data.m_vect.max_size(); } + + void swap(flat_tree& other) + { + value_compare& mycomp = this->m_data; + value_compare& othercomp = other.m_data; + containers_detail::do_swap(mycomp, othercomp); + vector_t & myvect = this->m_data.m_vect; + vector_t & othervect = other.m_data.m_vect; + myvect.swap(othervect); + } + + public: + // insert/erase + std::pair insert_unique(const value_type& val) + { + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(val, data); + if(ret.second){ + ret.first = priv_insert_commit(data, val); + } + return ret; + } + + std::pair insert_unique(BOOST_RV_REF(value_type) val) + { + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(val, data); + if(ret.second){ + ret.first = priv_insert_commit(data, boost::move(val)); + } + return ret; + } + + + iterator insert_equal(const value_type& val) + { + iterator i = this->upper_bound(KeyOfValue()(val)); + i = this->m_data.m_vect.insert(i, val); + return i; + } + + iterator insert_equal(BOOST_RV_REF(value_type) mval) + { + iterator i = this->upper_bound(KeyOfValue()(mval)); + i = this->m_data.m_vect.insert(i, boost::move(mval)); + return i; + } + + iterator insert_unique(const_iterator pos, const value_type& val) + { + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(pos, val, data); + if(ret.second){ + ret.first = priv_insert_commit(data, val); + } + return ret.first; + } + + iterator insert_unique(const_iterator pos, BOOST_RV_REF(value_type) mval) + { + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(pos, mval, data); + if(ret.second){ + ret.first = priv_insert_commit(data, boost::move(mval)); + } + return ret.first; + } + + iterator insert_equal(const_iterator pos, const value_type& val) + { + insert_commit_data data; + priv_insert_equal_prepare(pos, val, data); + return priv_insert_commit(data, val); + } + + iterator insert_equal(const_iterator pos, BOOST_RV_REF(value_type) mval) + { + insert_commit_data data; + priv_insert_equal_prepare(pos, mval, data); + return priv_insert_commit(data, boost::move(mval)); + } + + template + void insert_unique(InIt first, InIt last) + { + for ( ; first != last; ++first) + this->insert_unique(*first); + } + + template + void insert_equal(InIt first, InIt last) + { + typedef typename + std::iterator_traits::iterator_category ItCat; + priv_insert_equal(first, last, ItCat()); + } + + #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + template + iterator emplace_unique(Args&&... args) + { + value_type && val = value_type(boost::forward(args)...); + insert_commit_data data; + std::pair ret = + priv_insert_unique_prepare(val, data); + if(ret.second){ + ret.first = priv_insert_commit(data, boost::move(val)); + } + return ret.first; + } + + template + iterator emplace_hint_unique(const_iterator hint, Args&&... args) + { + value_type && val = value_type(boost::forward(args)...); + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(hint, val, data); + if(ret.second){ + ret.first = priv_insert_commit(data, boost::move(val)); + } + return ret.first; + } + + template + iterator emplace_equal(Args&&... args) + { + value_type &&val = value_type(boost::forward(args)...); + iterator i = this->upper_bound(KeyOfValue()(val)); + i = this->m_data.m_vect.insert(i, boost::move(val)); + return i; + } + + template + iterator emplace_hint_equal(const_iterator hint, Args&&... args) + { + value_type &&val = value_type(boost::forward(args)...); + insert_commit_data data; + priv_insert_equal_prepare(hint, val, data); + return priv_insert_commit(data, boost::move(val)); + } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator emplace_unique() + { + containers_detail::value_init vval; + value_type &val = vval.m_t; + insert_commit_data data; + std::pair ret = + priv_insert_unique_prepare(val, data); + if(ret.second){ + ret.first = priv_insert_commit(data, boost::move(val)); + } + return ret.first; + } + + iterator emplace_hint_unique(const_iterator hint) + { + containers_detail::value_init vval; + value_type &val = vval.m_t; + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(hint, val, data); + if(ret.second){ + ret.first = priv_insert_commit(data, boost::move(val)); + } + return ret.first; + } + + iterator emplace_equal() + { + containers_detail::value_init vval; + value_type &val = vval.m_t; + iterator i = this->upper_bound(KeyOfValue()(val)); + i = this->m_data.m_vect.insert(i, boost::move(val)); + return i; + } + + iterator emplace_hint_equal(const_iterator hint) + { + containers_detail::value_init vval; + value_type &val = vval.m_t; + insert_commit_data data; + priv_insert_equal_prepare(hint, val, data); + return priv_insert_commit(data, boost::move(val)); + } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + insert_commit_data data; \ + std::pair ret = priv_insert_unique_prepare(val, data); \ + if(ret.second){ \ + ret.first = priv_insert_commit(data, boost::move(val)); \ + } \ + return ret.first; \ + } \ + \ + template \ + iterator emplace_hint_unique(const_iterator hint, \ + BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + insert_commit_data data; \ + std::pair ret = priv_insert_unique_prepare(hint, val, data); \ + if(ret.second){ \ + ret.first = priv_insert_commit(data, boost::move(val)); \ + } \ + return ret.first; \ + } \ + \ + template \ + iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + iterator i = this->upper_bound(KeyOfValue()(val)); \ + i = this->m_data.m_vect.insert(i, boost::move(val)); \ + return i; \ + } \ + \ + template \ + iterator emplace_hint_equal(const_iterator hint, \ + BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + insert_commit_data data; \ + priv_insert_equal_prepare(hint, val, data); \ + return priv_insert_commit(data, boost::move(val)); \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator erase(const_iterator position) + { return this->m_data.m_vect.erase(position); } + + size_type erase(const key_type& k) + { + std::pair itp = this->equal_range(k); + size_type ret = static_cast(itp.second-itp.first); + if (ret){ + this->m_data.m_vect.erase(itp.first, itp.second); + } + return ret; + } + + iterator erase(const_iterator first, const_iterator last) + { return this->m_data.m_vect.erase(first, last); } + + void clear() + { this->m_data.m_vect.clear(); } + + //! Effects: Tries to deallocate the excess of memory created + // with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { this->m_data.m_vect.shrink_to_fit(); } + + // 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(); + } + 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(); + } + return i; + } + + size_type count(const key_type& k) const + { + std::pair p = this->equal_range(k); + size_type n = p.second - p.first; + return n; + } + + iterator lower_bound(const key_type& k) + { 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); } + + 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); } + + std::pair equal_range(const key_type& k) + { return this->priv_equal_range(this->begin(), this->end(), k); } + + std::pair equal_range(const key_type& k) const + { return this->priv_equal_range(this->begin(), this->end(), k); } + + size_type capacity() const + { return this->m_data.m_vect.capacity(); } + + void reserve(size_type count) + { this->m_data.m_vect.reserve(count); } + + private: + struct insert_commit_data + { + const_iterator position; + }; + + // insert/erase + void priv_insert_equal_prepare + (const_iterator pos, const value_type& val, insert_commit_data &data) + { + // N1780 + // To insert val at pos: + // if pos == end || val <= *pos + // if pos == begin || val >= *(pos-1) + // insert val before pos + // else + // insert val before upper_bound(val) + // else if pos+1 == end || val <= *(pos+1) + // 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(*pos, val)){ + if (pos == this->cbegin() || !value_comp(val, pos[-1])){ + data.position = pos; + } + else{ + data.position = + this->priv_upper_bound(this->cbegin(), pos, KeyOfValue()(val)); + } + } + //Works, but increases code complexity + //else if (++pos == this->end() || !value_comp(*pos, val)){ + // return this->m_data.m_vect.insert(pos, val); + //} + else{ + data.position = + this->priv_lower_bound(pos, this->cend(), KeyOfValue()(val)); + } + } + + std::pair priv_insert_unique_prepare + (const_iterator beg, const_iterator end, 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 + ( *reinterpret_cast(&commit_data.position) + , commit_data.position == end || value_comp(val, *commit_data.position)); + } + + std::pair 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); } + + std::pair priv_insert_unique_prepare + (const_iterator pos, const value_type& val, insert_commit_data &commit_data) + { + //N1780. Props to Howard Hinnant! + //To insert val at pos: + //if pos == end || val <= *pos + // if pos == begin || val >= *(pos-1) + // insert val before pos + // else + // insert val before upper_bound(val) + //else if pos+1 == end || val <= *(pos+1) + // 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(*reinterpret_cast(&pos), true); + } + else{ + return std::pair(*reinterpret_cast(&pos), false); + } + } + 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(pos+1, true); + // } + // else{ + // return std::pair(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); + } + } + + template + iterator priv_insert_commit + (insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible) + { + return this->m_data.m_vect.insert + ( commit_data.position + , boost::forward(convertible)); + } + + template + RanIt priv_lower_bound(RanIt first, RanIt last, + const key_type & key) const + { + const Compare &key_comp = this->m_data.get_comp(); + KeyOfValue key_extract; + difference_type len = last - first, half; + RanIt middle; + + while (len > 0) { + half = len >> 1; + middle = first; + middle += half; + + if (key_comp(key_extract(*middle), key)) { + ++middle; + first = middle; + len = len - half - 1; + } + else + len = half; + } + return first; + } + + template + RanIt priv_upper_bound(RanIt first, RanIt last, + const key_type & key) const + { + const Compare &key_comp = this->m_data.get_comp(); + KeyOfValue key_extract; + difference_type len = last - first, half; + RanIt middle; + + while (len > 0) { + half = len >> 1; + middle = first; + middle += half; + + if (key_comp(key, key_extract(*middle))) { + len = half; + } + else{ + first = ++middle; + len = len - half - 1; + } + } + return first; + } + + template + std::pair + priv_equal_range(RanIt first, RanIt last, const key_type& key) const + { + const Compare &key_comp = this->m_data.get_comp(); + KeyOfValue key_extract; + difference_type len = last - first, half; + RanIt middle, left, right; + + while (len > 0) { + half = len >> 1; + middle = first; + middle += half; + + if (key_comp(key_extract(*middle), key)){ + first = middle; + ++first; + len = len - half - 1; + } + else if (key_comp(key, key_extract(*middle))){ + len = half; + } + else { + left = this->priv_lower_bound(first, middle, key); + first += len; + right = this->priv_upper_bound(++middle, first, key); + return std::pair(left, right); + } + } + return std::pair(first, first); + } + + template + void priv_insert_equal(FwdIt first, FwdIt last, std::forward_iterator_tag) + { + size_type len = static_cast(std::distance(first, last)); + this->reserve(this->size()+len); + this->priv_insert_equal(first, last, std::input_iterator_tag()); + } + + template + void priv_insert_equal(InIt first, InIt last, std::input_iterator_tag) + { + for ( ; first != last; ++first) + this->insert_equal(*first); + } + +/* + template + void priv_insert_unique(FwdIt first, FwdIt last, std::forward_iterator_tag) + { + size_type len = static_cast(std::distance(first, last)); + this->reserve(this->size()+len); + priv_insert_unique(first, last, std::input_iterator_tag()); + } + + template + void priv_insert_unique(InIt first, InIt last, std::input_iterator_tag) + { + for ( ; first != last; ++first) + this->insert_unique(*first); + } +*/ +}; + +template +inline bool +operator==(const flat_tree& x, + const flat_tree& y) +{ + return x.size() == y.size() && + std::equal(x.begin(), x.end(), y.begin()); +} + +template +inline bool +operator<(const flat_tree& x, + const flat_tree& y) +{ + return std::lexicographical_compare(x.begin(), x.end(), + y.begin(), y.end()); +} + +template +inline bool +operator!=(const flat_tree& x, + const flat_tree& y) + { return !(x == y); } + +template +inline bool +operator>(const flat_tree& x, + const flat_tree& y) + { return y < x; } + +template +inline bool +operator<=(const flat_tree& x, + const flat_tree& y) + { return !(y < x); } + +template +inline bool +operator>=(const flat_tree& x, + const flat_tree& y) + { return !(x < y); } + + +template +inline void +swap(flat_tree& x, + flat_tree& y) + { x.swap(y); } + +} //namespace containers_detail { + +} //namespace container { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; +}; +*/ +} //namespace boost { + +#include + +#endif // BOOST_CONTAINERS_FLAT_TREE_HPP diff --git a/include/boost/container/detail/iterators.hpp b/include/boost/container/detail/iterators.hpp new file mode 100644 index 0000000..a83b472 --- /dev/null +++ b/include/boost/container/detail/iterators.hpp @@ -0,0 +1,546 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Gennaro Prota 2003 - 2004. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINERS_DETAIL_ITERATORS_HPP +#define BOOST_CONTAINERS_DETAIL_ITERATORS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include +#include + +#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING +#include +#include +#else +#include +#endif + +#include + +namespace boost { +namespace container { + +template +class constant_iterator + : public std::iterator + +{ + typedef constant_iterator this_type; + + public: + explicit constant_iterator(const T &ref, Difference range_size) + : m_ptr(&ref), m_num(range_size){} + + //Constructors + constant_iterator() + : m_ptr(0), m_num(0){} + + constant_iterator& operator++() + { increment(); return *this; } + + constant_iterator operator++(int) + { + constant_iterator result (*this); + increment(); + return result; + } + + constant_iterator& operator--() + { decrement(); return *this; } + + constant_iterator operator--(int) + { + constant_iterator result (*this); + decrement(); + return result; + } + + friend bool operator== (const constant_iterator& i, const constant_iterator& i2) + { return i.equal(i2); } + + friend bool operator!= (const constant_iterator& i, const constant_iterator& i2) + { return !(i == i2); } + + friend bool operator< (const constant_iterator& i, const constant_iterator& i2) + { return i.less(i2); } + + friend bool operator> (const constant_iterator& i, const constant_iterator& i2) + { return i2 < i; } + + friend bool operator<= (const constant_iterator& i, const constant_iterator& i2) + { return !(i > i2); } + + friend bool operator>= (const constant_iterator& i, const constant_iterator& i2) + { return !(i < i2); } + + friend Difference operator- (const constant_iterator& i, const constant_iterator& i2) + { return i2.distance_to(i); } + + //Arithmetic + constant_iterator& operator+=(Difference off) + { this->advance(off); return *this; } + + constant_iterator operator+(Difference off) const + { + constant_iterator other(*this); + other.advance(off); + return other; + } + + friend constant_iterator operator+(Difference off, const constant_iterator& right) + { return right + off; } + + constant_iterator& operator-=(Difference off) + { this->advance(-off); return *this; } + + constant_iterator operator-(Difference off) const + { return *this + (-off); } + + const T& operator*() const + { return dereference(); } + + const T& operator[] (Difference n) const + { return dereference(); } + + const T* operator->() const + { return &(dereference()); } + + private: + const T * m_ptr; + Difference m_num; + + void increment() + { --m_num; } + + void decrement() + { ++m_num; } + + bool equal(const this_type &other) const + { return m_num == other.m_num; } + + bool less(const this_type &other) const + { return other.m_num < m_num; } + + const T & dereference() const + { return *m_ptr; } + + void advance(Difference n) + { m_num -= n; } + + Difference distance_to(const this_type &other)const + { return m_num - other.m_num; } +}; + +template +class default_construct_iterator + : public std::iterator + +{ + typedef default_construct_iterator this_type; + + public: + explicit default_construct_iterator(Difference range_size) + : m_num(range_size){} + + //Constructors + default_construct_iterator() + : m_num(0){} + + default_construct_iterator& operator++() + { increment(); return *this; } + + default_construct_iterator operator++(int) + { + default_construct_iterator result (*this); + increment(); + return result; + } + + default_construct_iterator& operator--() + { decrement(); return *this; } + + default_construct_iterator operator--(int) + { + default_construct_iterator result (*this); + decrement(); + return result; + } + + friend bool operator== (const default_construct_iterator& i, const default_construct_iterator& i2) + { return i.equal(i2); } + + friend bool operator!= (const default_construct_iterator& i, const default_construct_iterator& i2) + { return !(i == i2); } + + friend bool operator< (const default_construct_iterator& i, const default_construct_iterator& i2) + { return i.less(i2); } + + friend bool operator> (const default_construct_iterator& i, const default_construct_iterator& i2) + { return i2 < i; } + + friend bool operator<= (const default_construct_iterator& i, const default_construct_iterator& i2) + { return !(i > i2); } + + friend bool operator>= (const default_construct_iterator& i, const default_construct_iterator& i2) + { return !(i < i2); } + + friend Difference operator- (const default_construct_iterator& i, const default_construct_iterator& i2) + { return i2.distance_to(i); } + + //Arithmetic + default_construct_iterator& operator+=(Difference off) + { this->advance(off); return *this; } + + default_construct_iterator operator+(Difference off) const + { + default_construct_iterator other(*this); + other.advance(off); + return other; + } + + friend default_construct_iterator operator+(Difference off, const default_construct_iterator& right) + { return right + off; } + + default_construct_iterator& operator-=(Difference off) + { this->advance(-off); return *this; } + + default_construct_iterator operator-(Difference off) const + { return *this + (-off); } + + const T& operator*() const + { return dereference(); } + + const T* operator->() const + { return &(dereference()); } + + const T& operator[] (Difference n) const + { return dereference(); } + + private: + Difference m_num; + + void increment() + { --m_num; } + + void decrement() + { ++m_num; } + + bool equal(const this_type &other) const + { return m_num == other.m_num; } + + bool less(const this_type &other) const + { return other.m_num < m_num; } + + const T & dereference() const + { + static T dummy; + return dummy; + } + + void advance(Difference n) + { m_num -= n; } + + Difference distance_to(const this_type &other)const + { return m_num - other.m_num; } +}; + +template +class repeat_iterator + : public std::iterator + +{ + typedef repeat_iterator this_type; + public: + explicit repeat_iterator(T &ref, Difference range_size) + : m_ptr(&ref), m_num(range_size){} + + //Constructors + repeat_iterator() + : m_ptr(0), m_num(0){} + + this_type& operator++() + { increment(); return *this; } + + this_type operator++(int) + { + this_type result (*this); + increment(); + return result; + } + + this_type& operator--() + { increment(); return *this; } + + this_type operator--(int) + { + this_type result (*this); + increment(); + return result; + } + + friend bool operator== (const this_type& i, const this_type& i2) + { return i.equal(i2); } + + friend bool operator!= (const this_type& i, const this_type& i2) + { return !(i == i2); } + + friend bool operator< (const this_type& i, const this_type& i2) + { return i.less(i2); } + + friend bool operator> (const this_type& i, const this_type& i2) + { return i2 < i; } + + friend bool operator<= (const this_type& i, const this_type& i2) + { return !(i > i2); } + + friend bool operator>= (const this_type& i, const this_type& i2) + { return !(i < i2); } + + friend Difference operator- (const this_type& i, const this_type& i2) + { return i2.distance_to(i); } + + //Arithmetic + this_type& operator+=(Difference off) + { this->advance(off); return *this; } + + this_type operator+(Difference off) const + { + this_type other(*this); + other.advance(off); + return other; + } + + friend this_type operator+(Difference off, const this_type& right) + { return right + off; } + + this_type& operator-=(Difference off) + { this->advance(-off); return *this; } + + this_type operator-(Difference off) const + { return *this + (-off); } + + T& operator*() const + { return dereference(); } + + T& operator[] (Difference n) const + { return dereference(); } + + T *operator->() const + { return &(dereference()); } + + private: + T * m_ptr; + Difference m_num; + + void increment() + { --m_num; } + + void decrement() + { ++m_num; } + + bool equal(const this_type &other) const + { return m_num == other.m_num; } + + bool less(const this_type &other) const + { return other.m_num < m_num; } + + T & dereference() const + { return *m_ptr; } + + void advance(Difference n) + { m_num -= n; } + + Difference distance_to(const this_type &other)const + { return m_num - other.m_num; } +}; + +template +class emplace_iterator + : public std::iterator + +{ + typedef emplace_iterator this_type; + + public: + typedef Difference difference_type; + explicit emplace_iterator(E&e) + : m_num(1), m_pe(&e){} + + emplace_iterator() + : m_num(0), m_pe(0){} + + this_type& operator++() + { increment(); return *this; } + + this_type operator++(int) + { + this_type result (*this); + increment(); + return result; + } + + this_type& operator--() + { decrement(); return *this; } + + this_type operator--(int) + { + this_type result (*this); + decrement(); + return result; + } + + friend bool operator== (const this_type& i, const this_type& i2) + { return i.equal(i2); } + + friend bool operator!= (const this_type& i, const this_type& i2) + { return !(i == i2); } + + friend bool operator< (const this_type& i, const this_type& i2) + { return i.less(i2); } + + friend bool operator> (const this_type& i, const this_type& i2) + { return i2 < i; } + + friend bool operator<= (const this_type& i, const this_type& i2) + { return !(i > i2); } + + friend bool operator>= (const this_type& i, const this_type& i2) + { return !(i < i2); } + + friend difference_type operator- (const this_type& i, const this_type& i2) + { return i2.distance_to(i); } + + //Arithmetic + this_type& operator+=(difference_type off) + { this->advance(off); return *this; } + + this_type operator+(difference_type off) const + { + this_type other(*this); + other.advance(off); + return other; + } + + friend this_type operator+(difference_type off, const this_type& right) + { return right + off; } + + this_type& operator-=(difference_type off) + { this->advance(-off); return *this; } + + 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()); } + + void construct_in_place(T* ptr) + { (*m_pe)(ptr); } + + private: + difference_type m_num; + E * m_pe; + + 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_type n) + { m_num -= n; } + + difference_type distance_to(const this_type &other)const + { return difference_type(m_num - other.m_num); } +}; + +#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + +template +struct emplace_functor +{ + typedef typename containers_detail::build_number_seq::type index_tuple_t; + + emplace_functor(Args&&... args) + : args_(args...) + {} + + void operator()(T *ptr) + { emplace_functor::inplace_impl(ptr, index_tuple_t()); } + + template + void inplace_impl(T* ptr, const containers_detail::index_tuple&) + { ::new(ptr) T(containers_detail::stored_ref::forward(containers_detail::get(args_))...); } + + containers_detail::tuple args_; +}; + +#else + +template +struct emplace_functor +{ + emplace_functor() + {} + void operator()(T *ptr) + { new(ptr) T(); } +}; + +#define BOOST_PP_LOCAL_MACRO(n) \ + template \ + struct BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \ + { \ + BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \ + ( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) ) \ + : BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {} \ + \ + void operator()(T *ptr) \ + { \ + new(ptr)T (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \ + } \ + BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _) \ + }; \ + //! +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) +#include BOOST_PP_LOCAL_ITERATE() + +#endif + +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINERS_DETAIL_ITERATORS_HPP + diff --git a/include/boost/container/detail/math_functions.hpp b/include/boost/container/detail/math_functions.hpp new file mode 100644 index 0000000..c7c443c --- /dev/null +++ b/include/boost/container/detail/math_functions.hpp @@ -0,0 +1,113 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Stephen Cleary 2000. +// (C) Copyright Ion Gaztanaga 2007-2011. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +// This file is a slightly modified file from Boost.Pool +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP +#define BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP + +#include "config_begin.hpp" +#include +#include + +namespace boost { +namespace container { +namespace containers_detail { + +// Greatest common divisor and least common multiple + +// +// gcd is an algorithm that calculates the greatest common divisor of two +// integers, using Euclid's algorithm. +// +// Pre: A > 0 && B > 0 +// Recommended: A > B +template +inline Integer gcd(Integer A, Integer B) +{ + do + { + const Integer tmp(B); + B = A % B; + A = tmp; + } while (B != 0); + + return A; +} + +// +// lcm is an algorithm that calculates the least common multiple of two +// integers. +// +// Pre: A > 0 && B > 0 +// Recommended: A > B +template +inline Integer lcm(const Integer & A, const Integer & B) +{ + Integer ret = A; + ret /= gcd(A, B); + ret *= B; + return ret; +} + +template +inline Integer log2_ceil(const Integer & A) +{ + Integer i = 0; + Integer power_of_2 = 1; + + while(power_of_2 < A){ + power_of_2 <<= 1; + ++i; + } + return i; +} + +template +inline Integer upper_power_of_2(const Integer & A) +{ + Integer power_of_2 = 1; + + while(power_of_2 < A){ + power_of_2 <<= 1; + } + return power_of_2; +} + +//This function uses binary search to discover the +//highest set bit of the integer +inline std::size_t floor_log2 (std::size_t x) +{ + const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT; + const bool Size_t_Bits_Power_2= !(Bits & (Bits-1)); + BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true)); + + std::size_t n = x; + std::size_t log2 = 0; + + for(std::size_t shift = Bits >> 1; shift; shift >>= 1){ + std::size_t tmp = n >> shift; + if (tmp) + log2 += shift, n = tmp; + } + + return log2; +} + +} // namespace containers_detail +} // namespace container +} // namespace boost + +#include + +#endif diff --git a/include/boost/container/detail/mpl.hpp b/include/boost/container/detail/mpl.hpp new file mode 100644 index 0000000..d0741fa --- /dev/null +++ b/include/boost/container/detail/mpl.hpp @@ -0,0 +1,155 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. +// +// 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_CONTAINERS_CONTAINER_DETAIL_MPL_HPP +#define BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include + +namespace boost { +namespace container { +namespace containers_detail { + +template +struct integral_constant +{ + static const T value = val; + typedef integral_constant type; +}; + +template< bool C_ > +struct bool_ : integral_constant +{ + static const bool value = C_; +}; + +typedef bool_ true_; +typedef bool_ false_; + +typedef true_ true_type; +typedef false_ false_type; + +typedef char yes_type; +struct no_type +{ + char padding[8]; +}; + +template +struct enable_if_c { + typedef T type; +}; + +template +struct enable_if_c {}; + +template +struct enable_if : public enable_if_c {}; + +template +struct disable_if : public enable_if_c {}; + +template +struct disable_if_c : public enable_if_c {}; + +template +class is_convertible +{ + typedef char true_t; + class false_t { char dummy[2]; }; + static true_t dispatch(U); + static false_t dispatch(...); + static T trigger(); + public: + enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) }; +}; + +template< + bool C + , typename T1 + , typename T2 + > +struct if_c +{ + typedef T1 type; +}; + +template< + typename T1 + , typename T2 + > +struct if_c +{ + typedef T2 type; +}; + +template< + typename T1 + , typename T2 + , typename T3 + > +struct if_ +{ + typedef typename if_c<0 != T1::value, T2, T3>::type type; +}; + + +template +struct select1st +// : public std::unary_function +{ + template + const typename Pair::first_type& operator()(const OtherPair& x) const + { return x.first; } + + const typename Pair::first_type& operator()(const typename Pair::first_type& x) const + { return x; } +}; + +// identity is an extension: it is not part of the standard. +template +struct identity +// : public std::unary_function +{ + typedef T type; + const T& operator()(const T& x) const + { return x; } +}; + +template +struct ls_zeros +{ + static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value); +}; + +template<> +struct ls_zeros<0> +{ + static const std::size_t value = 0; +}; + +template<> +struct ls_zeros<1> +{ + static const std::size_t value = 0; +}; + +} //namespace containers_detail { +} //namespace container { +} //namespace boost { + +#endif //#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP + diff --git a/include/boost/container/detail/multiallocation_chain.hpp b/include/boost/container/detail/multiallocation_chain.hpp new file mode 100644 index 0000000..52e0cb7 --- /dev/null +++ b/include/boost/container/detail/multiallocation_chain.hpp @@ -0,0 +1,252 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP +#define BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP + +#include "config_begin.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace container { +namespace containers_detail { + +template +class basic_multiallocation_chain +{ + private: + typedef bi::slist_base_hook + ,bi::link_mode + > node; + + typedef typename boost::pointer_to_other::type char_ptr; + typedef typename std::iterator_traits::difference_type difference_type; + + typedef bi::slist< node + , bi::linear + , bi::cache_last + , bi::size_type::type> + > slist_impl_t; + slist_impl_t slist_impl_; + + static node & to_node(VoidPointer p) + { return *static_cast(static_cast(containers_detail::get_pointer(p))); } + + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain) + + public: + + + typedef VoidPointer void_pointer; + typedef typename slist_impl_t::iterator iterator; + typedef typename slist_impl_t::size_type size_type; + + basic_multiallocation_chain() + : slist_impl_() + {} + + basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other) + : slist_impl_() + { slist_impl_.swap(other.slist_impl_); } + + basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other) + { + basic_multiallocation_chain tmp(boost::move(other)); + this->swap(tmp); + return *this; + } + + bool empty() const + { return slist_impl_.empty(); } + + size_type size() const + { return slist_impl_.size(); } + + iterator before_begin() + { return slist_impl_.before_begin(); } + + iterator begin() + { return slist_impl_.begin(); } + + iterator end() + { return slist_impl_.end(); } + + iterator last() + { return slist_impl_.last(); } + + void clear() + { slist_impl_.clear(); } + + iterator insert_after(iterator it, void_pointer m) + { return slist_impl_.insert_after(it, to_node(m)); } + + void push_front(void_pointer m) + { return slist_impl_.push_front(to_node(m)); } + + void push_back(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 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) + { 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 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 swap(basic_multiallocation_chain &x) + { slist_impl_.swap(x.slist_impl_); } + + static iterator iterator_to(void_pointer p) + { return slist_impl_t::s_iterator_to(to_node(p)); } + + std::pair extract_data() + { + std::pair ret + (slist_impl_.begin().operator->() + ,slist_impl_.last().operator->()); + slist_impl_.clear(); + return ret; + } +}; + +template +struct cast_functor +{ + typedef typename containers_detail::add_reference::type result_type; + template + result_type operator()(U &ptr) const + { return *static_cast(static_cast(&ptr)); } +}; + +template +class transform_multiallocation_chain +{ + private: + BOOST_MOVABLE_BUT_NOT_COPYABLE(transform_multiallocation_chain) + + MultiallocationChain holder_; + typedef typename MultiallocationChain::void_pointer void_pointer; + typedef typename boost::pointer_to_other + ::type pointer; + + static pointer cast(void_pointer p) + { + return pointer(static_cast(containers_detail::get_pointer(p))); + } + + public: + typedef transform_iterator + < typename MultiallocationChain::iterator + , containers_detail::cast_functor > iterator; + typedef typename MultiallocationChain::size_type size_type; + + transform_multiallocation_chain() + : holder_() + {} + + transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other) + : holder_() + { this->swap(other); } + + transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other) + : holder_(boost::move(other)) + {} + + transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other) + { + transform_multiallocation_chain tmp(boost::move(other)); + this->swap(tmp); + return *this; + } + + void push_front(pointer mem) + { holder_.push_front(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()); } + + bool empty() const + { return holder_.empty(); } + + iterator before_begin() + { return iterator(holder_.before_begin()); } + + iterator begin() + { return iterator(holder_.begin()); } + + iterator end() + { return iterator(holder_.end()); } + + iterator last() + { return iterator(holder_.last()); } + + size_type size() const + { return holder_.size(); } + + void clear() + { holder_.clear(); } + + iterator insert_after(iterator it, pointer m) + { return iterator(holder_.insert_after(it.base(), m)); } + + static iterator iterator_to(pointer p) + { return iterator(MultiallocationChain::iterator_to(p)); } + + std::pair extract_data() + { return holder_.extract_data(); } + + MultiallocationChain extract_multiallocation_chain() + { + return MultiallocationChain(boost::move(holder_)); + } +}; + +}}} + +// namespace containers_detail { +// namespace container { +// namespace boost { + +#include + +#endif //BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp new file mode 100644 index 0000000..f2e88ef --- /dev/null +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -0,0 +1,501 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_DETAIL_NODE_ALLOC_HPP_ +#define BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_ + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING +#include +#endif + +#include + + +namespace boost { +namespace container { +namespace containers_detail { + +//!A deleter for scoped_ptr that deallocates the memory +//!allocated for an object using a STL allocator. +template +struct scoped_deallocator +{ + typedef typename Allocator::pointer pointer; + typedef containers_detail::integral_constant::value> alloc_version; + typedef containers_detail::integral_constant allocator_v1; + typedef containers_detail::integral_constant 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; + Allocator& m_alloc; + + scoped_deallocator(pointer p, Allocator& a) + : m_ptr(p), m_alloc(a) + {} + + ~scoped_deallocator() + { if (m_ptr)priv_deallocate(alloc_version()); } + + scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o) + : m_ptr(o.m_ptr), m_alloc(o.m_alloc) + { o.release(); } + + pointer get() const + { return m_ptr; } + + void release() + { m_ptr = 0; } +}; + +template +class allocator_destroyer_and_chain_builder +{ + typedef typename A::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) + { + value_type *vp = containers_detail::get_pointer(p); + vp->~value_type(); + c_.push_front(vp); + } +}; + +template +class allocator_multialloc_chain_node_deallocator +{ + typedef typename A::value_type value_type; + typedef typename A::multiallocation_chain multiallocation_chain; + typedef allocator_destroyer_and_chain_builder 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 +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; + + node_compare(const ValueCompare &pred) + : ValueCompare(pred) + {} + + ValueCompare &value_comp() + { return static_cast(*this); } + + ValueCompare &value_comp() const + { return static_cast(*this); } + + bool operator()(const Node &a, const Node &b) const + { return ValueCompare::operator()(a.get_data(), b.get_data()); } +}; + +template +struct node_alloc_holder +{ + typedef node_alloc_holder self_t; + typedef typename A::value_type value_type; + typedef typename ICont::value_type Node; + typedef typename A::template rebind::other NodeAlloc; + typedef A ValAlloc; + typedef typename NodeAlloc::pointer NodePtr; + typedef containers_detail::scoped_deallocator Deallocator; + typedef typename NodeAlloc::size_type size_type; + typedef typename NodeAlloc::difference_type difference_type; + typedef containers_detail::integral_constant allocator_v1; + typedef containers_detail::integral_constant allocator_v2; + typedef containers_detail::integral_constant::value> alloc_version; + typedef typename ICont::iterator icont_iterator; + typedef typename ICont::const_iterator icont_citerator; + typedef allocator_destroyer Destroyer; + + private: + BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder) + + public: + + node_alloc_holder(const ValAlloc &a) + : members_(a) + {} + + node_alloc_holder(const node_alloc_holder &other) + : members_(other.node_alloc()) + {} + + node_alloc_holder(BOOST_RV_REF(node_alloc_holder) other) + : members_(boost::move(other.node_alloc())) + { this->swap(other); } + + node_alloc_holder & operator=(BOOST_COPY_ASSIGN_REF(node_alloc_holder) other) + { members_.assign(other.node_alloc()); } + + node_alloc_holder & operator=(BOOST_RV_REF(node_alloc_holder) other) + { members_.assign(other.node_alloc()); } + + template + node_alloc_holder(const ValAlloc &a, const Pred &c) + : members_(a, typename ICont::value_compare(c)) + {} + + template + node_alloc_holder(BOOST_RV_REF(ValAlloc) a, const Pred &c) + : members_(a, typename ICont::value_compare(c)) + {} + + template + node_alloc_holder(const node_alloc_holder &other, const Pred &c) + : members_(other.node_alloc(), typename ICont::value_compare(c)) + {} + + ~node_alloc_holder() + { this->clear(alloc_version()); } + + size_type max_size() const + { return this->node_alloc().max_size(); } + + 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(); } + + void deallocate_one(NodePtr p) + { return this->deallocate_one(p, alloc_version()); } + + void deallocate_one(NodePtr p, allocator_v1) + { this->node_alloc().deallocate(p, 1); } + + void deallocate_one(NodePtr p, allocator_v2) + { this->node_alloc().deallocate_one(p); } + + template + static void construct(const NodePtr &ptr, + BOOST_RV_REF_2_TEMPL_ARGS(std::pair, Convertible1, Convertible2) value) + { + typedef typename Node::hook_type hook_type; + typedef typename Node::value_type::first_type first_type; + typedef typename Node::value_type::second_type second_type; + Node *nodeptr = containers_detail::get_pointer(ptr); + + //Hook constructor does not throw + new(static_cast(nodeptr))hook_type(); + //Now construct pair members_holder + value_type *valueptr = &nodeptr->get_data(); + new((void*)&valueptr->first) first_type(boost::move(value.first)); + BOOST_TRY{ + new((void*)&valueptr->second) second_type(boost::move(value.second)); + } + BOOST_CATCH(...){ + valueptr->first.~first_type(); + static_cast(nodeptr)->~hook_type(); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + static void destroy(const NodePtr &ptr) + { containers_detail::get_pointer(ptr)->~Node(); } + + Deallocator create_node_and_deallocator() + { + return Deallocator(this->allocate_one(), this->node_alloc()); + } + + #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + template + static void construct(const NodePtr &ptr, Args &&...args) + { new((void*)containers_detail::get_pointer(ptr)) Node(boost::forward(args)...); } + + template + NodePtr create_node(Args &&...args) + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + self_t::construct(p, boost::forward(args)...); + node_deallocator.release(); + return (p); + } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + static void construct(const NodePtr &ptr) + { new((void*)containers_detail::get_pointer(ptr)) Node(); } + + NodePtr create_node() + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + self_t::construct(p); + node_deallocator.release(); + return (p); + } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + void construct(const NodePtr &ptr, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + new((void*)containers_detail::get_pointer(ptr)) \ + Node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + NodePtr create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + NodePtr p = this->allocate_one(); \ + Deallocator node_deallocator(p, this->node_alloc()); \ + self_t::construct(p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + node_deallocator.release(); \ + return (p); \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + template + NodePtr create_node_from_it(It it) + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + ::boost::container::construct_in_place(containers_detail::get_pointer(p), it); + node_deallocator.release(); + return (p); + } + + void destroy_node(NodePtr node) + { + self_t::destroy(node); + this->deallocate_one(node); + } + + void swap(node_alloc_holder &x) + { + NodeAlloc& this_alloc = this->node_alloc(); + NodeAlloc& other_alloc = x.node_alloc(); + + if (this_alloc != other_alloc){ + containers_detail::do_swap(this_alloc, other_alloc); + } + + this->icont().swap(x.icont()); + } + + template + FwdIterator allocate_many_and_construct + (FwdIterator beg, difference_type n, Inserter inserter) + { + if(n){ + typedef typename NodeAlloc::multiallocation_chain multiallocation_chain; + + //Try to allocate memory in a single block + multiallocation_chain mem(this->node_alloc().allocate_individual(n)); + int constructed = 0; + Node *p = 0; + BOOST_TRY{ + for(difference_type i = 0; i < n; ++i, ++beg, --constructed){ + p = containers_detail::get_pointer(mem.front()); + mem.pop_front(); + //This can throw + constructed = 0; + boost::container::construct_in_place(p, beg); + ++constructed; + //This can throw in some containers (predicate might throw) + inserter(*p); + } + } + BOOST_CATCH(...){ + if(constructed){ + this->destroy(p); + } + this->node_alloc().deallocate_individual(boost::move(mem)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + return beg; + } + + void clear(allocator_v1) + { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); } + + void clear(allocator_v2) + { + typename NodeAlloc::multiallocation_chain chain; + allocator_destroyer_and_chain_builder builder(this->node_alloc(), chain); + this->icont().clear_and_dispose(builder); + //BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled::value == true)); + if(!chain.empty()) + this->node_alloc().deallocate_individual(boost::move(chain)); + } + + icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v1) + { return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); } + + icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v2) + { + allocator_multialloc_chain_node_deallocator chain_holder(this->node_alloc()); + return this->icont().erase_and_dispose(first, last, chain_holder.get_chain_builder()); + } + + template + size_type erase_key(const Key& k, const Comparator &comp, allocator_v1) + { return this->icont().erase_and_dispose(k, comp, Destroyer(this->node_alloc())); } + + template + size_type erase_key(const Key& k, const Comparator &comp, allocator_v2) + { + allocator_multialloc_chain_node_deallocator chain_holder(this->node_alloc()); + return this->icont().erase_and_dispose(k, comp, chain_holder.get_chain_builder()); + } + + protected: + struct cloner + { + cloner(node_alloc_holder &holder) + : m_holder(holder) + {} + + NodePtr operator()(const Node &other) const + { return m_holder.create_node(other.get_data()); } + + node_alloc_holder &m_holder; + }; + + struct destroyer + { + destroyer(node_alloc_holder &holder) + : m_holder(holder) + {} + + void operator()(NodePtr n) const + { m_holder.destroy_node(n); } + + node_alloc_holder &m_holder; + }; + + struct members_holder + : public NodeAlloc + { + private: + members_holder(const members_holder&); + + public: + template + members_holder(const ConvertibleToAlloc &c2alloc) + : NodeAlloc(c2alloc) + {} + + template + members_holder(const ConvertibleToAlloc &c2alloc, const Pred &c) + : NodeAlloc(c2alloc), m_icont(c) + {} + + template + void assign (const ConvertibleToAlloc &c2alloc) + { + NodeAlloc::operator=(c2alloc); + } + + //The intrusive container + ICont m_icont; + } members_; + + ICont &non_const_icont() const + { return const_cast(this->members_.m_icont); } + + ICont &icont() + { return this->members_.m_icont; } + + const ICont &icont() const + { return this->members_.m_icont; } + + NodeAlloc &node_alloc() + { return static_cast(this->members_); } + + const NodeAlloc &node_alloc() const + { return static_cast(this->members_); } +}; + +} //namespace containers_detail { +} //namespace container { +} //namespace boost { + +#include + +#endif // BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_ diff --git a/include/boost/container/detail/node_pool_impl.hpp b/include/boost/container/detail/node_pool_impl.hpp new file mode 100644 index 0000000..56bd144 --- /dev/null +++ b/include/boost/container/detail/node_pool_impl.hpp @@ -0,0 +1,367 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP +#define BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //std::unary_function + +namespace boost { +namespace container { +namespace containers_detail { + +template +class private_node_pool_impl +{ + //Non-copyable + private_node_pool_impl(); + private_node_pool_impl(const private_node_pool_impl &); + private_node_pool_impl &operator=(const private_node_pool_impl &); + + //A node object will hold node_t when it's not allocated + public: + typedef typename SegmentManagerBase::void_pointer void_pointer; + typedef typename node_slist::slist_hook_t slist_hook_t; + typedef typename node_slist::node_t node_t; + typedef typename node_slist::node_slist_t free_nodes_t; + typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain; + typedef typename SegmentManagerBase::size_type size_type; + + private: + typedef typename bi::make_slist + < node_t, bi::base_hook + , bi::linear + , bi::constant_time_size >::type blockslist_t; + public: + + //!Segment manager typedef + typedef SegmentManagerBase segment_manager_base_type; + + //!Constructor from a segment manager. Never throws + private_node_pool_impl(segment_manager_base_type *segment_mngr_base, size_type node_size, size_type nodes_per_block) + : m_nodes_per_block(nodes_per_block) + , m_real_node_size(lcm(node_size, size_type(alignment_of::value))) + //General purpose allocator + , mp_segment_mngr_base(segment_mngr_base) + , m_blocklist() + , m_freelist() + //Debug node count + , m_allocated(0) + {} + + //!Destructor. Deallocates all allocated blocks. Never throws + ~private_node_pool_impl() + { this->purge_blocks(); } + + size_type get_real_num_node() const + { return m_nodes_per_block; } + + //!Returns the segment manager. Never throws + segment_manager_base_type* get_segment_manager_base()const + { return containers_detail::get_pointer(mp_segment_mngr_base); } + + void *allocate_node() + { return priv_alloc_node(); } + + //!Deallocates an array pointed by ptr. Never throws + void deallocate_node(void *ptr) + { priv_dealloc_node(ptr); } + + //!Allocates a singly linked list of n nodes ending in null pointer. + multiallocation_chain allocate_nodes(const size_type n) + { + //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); + } + + //We just iterate the needed nodes to get the last we'll erase + typedef typename free_nodes_t::iterator free_iterator; + free_iterator before_last_new_it = m_freelist.before_begin(); + for(size_type j = 0; j != n; ++j){ + ++before_last_new_it; + } + + //Cache the first node of the allocated range before erasing + free_iterator first_node(m_freelist.begin()); + free_iterator last_node (before_last_new_it); + + //Erase the range. Since we already have the distance, this is O(1) + m_freelist.erase_after( m_freelist.before_begin() + , ++free_iterator(before_last_new_it) + , n); + + //Now take the last erased node and just splice it in the end + //of the intrusive list that will be traversed by the multialloc iterator. + 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) + { + typedef typename multiallocation_chain::iterator iterator; + iterator it(chain.begin()), itend(chain.end()); + while(it != itend){ + void *pElem = &*it; + ++it; + priv_dealloc_node(pElem); + } + } + + //!Deallocates all the free blocks of memory. Never throws + void deallocate_free_blocks() + { + typedef typename free_nodes_t::iterator nodelist_iterator; + typename blockslist_t::iterator bit(m_blocklist.before_begin()), + it(m_blocklist.begin()), + itend(m_blocklist.end()); + free_nodes_t backup_list; + nodelist_iterator backup_list_last = backup_list.before_begin(); + + //Execute the algorithm and get an iterator to the last value + size_type blocksize = get_rounded_size + (m_real_node_size*m_nodes_per_block, (size_type) alignment_of::value); + + while(it != itend){ + //Collect all the nodes from the block pointed by it + //and push them in the list + free_nodes_t free_nodes; + nodelist_iterator last_it = free_nodes.before_begin(); + const void *addr = get_block_from_hook(&*it, blocksize); + + m_freelist.remove_and_dispose_if + (is_between(addr, blocksize), push_in_list(free_nodes, last_it)); + + //If the number of nodes is equal to m_nodes_per_block + //this means that the block can be deallocated + if(free_nodes.size() == m_nodes_per_block){ + //Unlink the nodes + free_nodes.clear(); + it = m_blocklist.erase_after(bit); + mp_segment_mngr_base->deallocate((void*)addr); + } + //Otherwise, insert them in the backup list, since the + //next "remove_if" does not need to check them again. + else{ + //Assign the iterator to the last value if necessary + if(backup_list.empty() && !m_freelist.empty()){ + backup_list_last = last_it; + } + //Transfer nodes. This is constant time. + backup_list.splice_after + ( backup_list.before_begin() + , free_nodes + , free_nodes.before_begin() + , last_it + , free_nodes.size()); + bit = it; + ++it; + } + } + //We should have removed all the nodes from the free list + BOOST_ASSERT(m_freelist.empty()); + + //Now pass all the node to the free list again + m_freelist.splice_after + ( m_freelist.before_begin() + , backup_list + , backup_list.before_begin() + , backup_list_last + , backup_list.size()); + } + + size_type num_free_nodes() + { return m_freelist.size(); } + + //!Deallocates all used memory. Precondition: all nodes allocated from this pool should + //!already be deallocated. Otherwise, undefined behaviour. Never throws + void purge_blocks() + { + //check for memory leaks + BOOST_ASSERT(m_allocated==0); + size_type blocksize = get_rounded_size + (m_real_node_size*m_nodes_per_block, (size_type)alignment_of::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()){ + void *addr = get_block_from_hook(&m_blocklist.front(), blocksize); + m_blocklist.pop_front(); + mp_segment_mngr_base->deallocate((void*)addr); + } + //Just clear free node list + m_freelist.clear(); + } + + void swap(private_node_pool_impl &other) + { + BOOST_ASSERT(m_nodes_per_block == other.m_nodes_per_block); + BOOST_ASSERT(m_real_node_size == other.m_real_node_size); + std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base); + m_blocklist.swap(other.m_blocklist); + m_freelist.swap(other.m_freelist); + std::swap(m_allocated, other.m_allocated); + } + + private: + + struct push_in_list + { + push_in_list(free_nodes_t &l, typename free_nodes_t::iterator &it) + : slist_(l), last_it_(it) + {} + + void operator()(typename free_nodes_t::pointer p) const + { + slist_.push_front(*p); + if(slist_.size() == 1){ //Cache last element + ++last_it_ = slist_.begin(); + } + } + + private: + free_nodes_t &slist_; + typename free_nodes_t::iterator &last_it_; + }; + + struct is_between + : std::unary_function + { + is_between(const void *addr, std::size_t size) + : beg_(static_cast(addr)), end_(beg_+size) + {} + + bool operator()(typename free_nodes_t::const_reference v) const + { + return (beg_ <= reinterpret_cast(&v) && + end_ > reinterpret_cast(&v)); + } + private: + const char * beg_; + const char * end_; + }; + + //!Allocates one node, using single segregated storage algorithm. + //!Never throws + node_t *priv_alloc_node() + { + //If there are no free nodes we allocate a new block + if (m_freelist.empty()) + priv_alloc_block(); + //We take the first free node + node_t *n = (node_t*)&m_freelist.front(); + m_freelist.pop_front(); + ++m_allocated; + return n; + } + + //!Deallocates one node, using single segregated storage algorithm. + //!Never throws + void priv_dealloc_node(void *pElem) + { + //We put the node at the beginning of the free node list + node_t * to_deallocate = static_cast(pElem); + m_freelist.push_front(*to_deallocate); + BOOST_ASSERT(m_allocated>0); + --m_allocated; + } + + //!Allocates several blocks of nodes. Can throw + void priv_alloc_block(size_type num_blocks = 1) + { + if(!num_blocks) + return; + size_type blocksize = + get_rounded_size(m_real_node_size*m_nodes_per_block, (size_type)alignment_of::value); + + try{ + for(size_type i = 0; i != num_blocks; ++i){ + //We allocate a new NodeBlock and put it as first + //element in the free Node list + char *pNode = reinterpret_cast + (mp_segment_mngr_base->allocate(blocksize + sizeof(node_t))); + char *pBlock = pNode; + m_blocklist.push_front(get_block_hook(pBlock, blocksize)); + + //We initialize all Nodes in Node Block to insert + //them in the free Node list + for(size_type i = 0; i < m_nodes_per_block; ++i, pNode += m_real_node_size){ + m_freelist.push_front(*new (pNode) node_t); + } + } + } + catch(...){ + //to-do: if possible, an efficient way to deallocate allocated blocks + throw; + } + } + + //!Deprecated, use deallocate_free_blocks + void deallocate_free_chunks() + { this->deallocate_free_blocks(); } + + //!Deprecated, use purge_blocks + void purge_chunks() + { this->purge_blocks(); } + + private: + //!Returns a reference to the block hook placed in the end of the block + static node_t & get_block_hook (void *block, size_type blocksize) + { + return *reinterpret_cast(reinterpret_cast(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(hook) - blocksize); + } + + private: + typedef typename boost::pointer_to_other + ::type segment_mngr_base_ptr_t; + + const size_type m_nodes_per_block; + const size_type m_real_node_size; + segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager + blockslist_t m_blocklist; //Intrusive container of blocks + free_nodes_t m_freelist; //Intrusive container of free nods + size_type m_allocated; //Used nodes for debugging +}; + + +} //namespace containers_detail { +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP diff --git a/include/boost/container/detail/pair.hpp b/include/boost/container/detail/pair.hpp new file mode 100644 index 0000000..fd98a72 --- /dev/null +++ b/include/boost/container/detail/pair.hpp @@ -0,0 +1,320 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. +// +// 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_CONTAINERS_CONTAINERS_DETAIL_PAIR_HPP +#define BOOST_CONTAINERS_CONTAINERS_DETAIL_PAIR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include + +#include +#include + +#include //std::pair + +#include +#include + +#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING +#include +#endif + +namespace boost { +namespace container { +namespace containers_detail { + +template +struct pair; + +template +struct is_pair +{ + static const bool value = false; +}; + +template +struct is_pair< pair > +{ + static const bool value = true; +}; + +template +struct is_pair< std::pair > +{ + static const bool value = true; +}; + +struct pair_nat; + +struct piecewise_construct_t { }; +static const piecewise_construct_t piecewise_construct = piecewise_construct_t(); + +template +struct pair +{ + private: + BOOST_COPYABLE_AND_MOVABLE(pair) + + public: + typedef T1 first_type; + typedef T2 second_type; + + T1 first; + T2 second; + + //Default constructor + pair() + : first(), second() + {} +/* + //pair from two values + pair(const T1 &t1, const T2 &t2) + : first(t1) + , second(t2) + {} + + + //pair from two values + pair(BOOST_RV_REF(T1) t1, BOOST_RV_REF(T2) t2) + : first(::boost::move(t1)) + , second(::boost::move(t2)) + {} +*/ + template + pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v) + : first(::boost::forward(u)) + , second(::boost::forward(v)) + {} + + //pair copy assignment + pair(const pair& x) + : first(x.first), second(x.second) + {} + + template + pair(const pair &p) + : first(p.first), second(p.second) + {} + + //pair move constructor + pair(BOOST_RV_REF(pair) p) + : first(::boost::move(p.first)), second(::boost::move(p.second)) + {} + + template + pair(BOOST_RV_REF_2_TEMPL_ARGS(pair, D, S) p) + : first(::boost::move(p.first)), second(::boost::move(p.second)) + {} + + //std::pair copy constructor + pair(const std::pair& x) + : first(x.first), second(x.second) + {} + + template + pair(const std::pair& p) + : first(p.first), second(p.second) + {} + + //std::pair move constructor + template + pair(BOOST_RV_REF_2_TEMPL_ARGS(std::pair, D, S) p) + : first(::boost::move(p.first)), second(::boost::move(p.second)) + {} + + pair(BOOST_RV_REF_2_TEMPL_ARGS(std::pair, T1, T2) p) + : first(::boost::move(p.first)), second(::boost::move(p.second)) + {} + + //piecewise_construct missing +/* + //Variadic versions + template + pair(BOOST_CONTAINERS_PARAM(U, u), typename containers_detail::disable_if + < containers_detail::is_pair< typename containers_detail::remove_ref_const::type >, pair_nat>::type* = 0) + : first(::boost::forward(u)) + , second() + {} + + #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + template + pair(U &&u, V &&v) + : first(::boost::forward(u)) + , second(::boost::forward(v), ::boost::forward(args)...) + {} + + #else + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + pair(BOOST_CONTAINERS_PARAM(U, u) \ + ,BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + : first(::boost::forward(u)) \ + , second(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \ + {} \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + #endif +*/ + //pair copy assignment + pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p) + { + first = p.first; + second = p.second; + return *this; + } + + template + pair& operator=(const pair&p) + { + first = p.first; + second = p.second; + return *this; + } + + //pair move assignment + pair& operator=(BOOST_RV_REF(pair) p) + { + first = ::boost::move(p.first); + second = ::boost::move(p.second); + return *this; + } + + template + pair& operator=(BOOST_RV_REF_2_TEMPL_ARGS(pair, D, S) p) + { + first = ::boost::move(p.first); + second = ::boost::move(p.second); + return *this; + } + + //std::pair copy assignment + pair& operator=(const std::pair &p) + { + first = p.first; + second = p.second; + return *this; + } + + template + pair& operator=(const std::pair &p) + { + first = ::boost::move(p.first); + second = ::boost::move(p.second); + return *this; + } + + //std::pair move assignment + pair& operator=(BOOST_RV_REF_2_TEMPL_ARGS(std::pair, T1, T2) p) + { + first = ::boost::move(p.first); + second = ::boost::move(p.second); + return *this; + } + + template + pair& operator=(BOOST_RV_REF_2_TEMPL_ARGS(std::pair, D, S) p) + { + first = ::boost::move(p.first); + second = ::boost::move(p.second); + return *this; + } + + //swap + void swap(pair& p) + { + using std::swap; + swap(this->first, p.first); + swap(this->second, p.second); + } +}; + +template +inline bool operator==(const pair& x, const pair& y) +{ return static_cast(x.first == y.first && x.second == y.second); } + +template +inline bool operator< (const pair& x, const pair& y) +{ return static_cast(x.first < y.first || + (!(y.first < x.first) && x.second < y.second)); } + +template +inline bool operator!=(const pair& x, const pair& y) +{ return static_cast(!(x == y)); } + +template +inline bool operator> (const pair& x, const pair& y) +{ return y < x; } + +template +inline bool operator>=(const pair& x, const pair& y) +{ return static_cast(!(x < y)); } + +template +inline bool operator<=(const pair& x, const pair& y) +{ return static_cast(!(y < x)); } + +template +inline pair make_pair(T1 x, T2 y) +{ return pair(x, y); } + +template +inline void swap(pair& x, pair& y) +{ + swap(x.first, y.first); + swap(x.second, y.second); +} + +} //namespace containers_detail { +} //namespace container { + + +//Without this specialization recursive flat_(multi)map instantiation fails +//because is_enum needs to instantiate the recursive pair, leading to a compilation error). +//This breaks the cycle clearly stating that pair is not an enum avoiding any instantiation. +template +struct is_enum; + +template +struct is_enum< ::boost::container::containers_detail::pair > +{ + static const bool value = false; +}; + +//This specialization is needed to avoid instantiation of pair in +//is_class, and allow recursive maps. +template +struct is_class< ::boost::container::containers_detail::pair > + : public ::boost::true_type +{}; + +#ifdef BOOST_NO_RVALUE_REFERENCES + +template +struct has_move_emulation_enabled< ::boost::container::containers_detail::pair > + : ::boost::true_type +{}; + +#endif + + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINERS_DETAIL_PAIR_HPP diff --git a/include/boost/container/detail/pool_common.hpp b/include/boost/container/detail/pool_common.hpp new file mode 100644 index 0000000..c647710 --- /dev/null +++ b/include/boost/container/detail/pool_common.hpp @@ -0,0 +1,52 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_COMMON_HPP +#define BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include +#include + +namespace boost { +namespace container { +namespace containers_detail { + +template +struct node_slist +{ + //This hook will be used to chain the individual nodes + typedef typename bi::make_slist_base_hook + , bi::link_mode >::type slist_hook_t; + + //A node object will hold node_t when it's not allocated + typedef slist_hook_t node_t; + + typedef typename bi::make_slist + , bi::base_hook >::type node_slist_t; +}; + +template +struct is_stateless_segment_manager +{ + static const bool value = false; +}; + +} //namespace containers_detail { +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP diff --git a/include/boost/container/detail/preprocessor.hpp b/include/boost/container/detail/preprocessor.hpp new file mode 100644 index 0000000..72a5904 --- /dev/null +++ b/include/boost/container/detail/preprocessor.hpp @@ -0,0 +1,141 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-2011. 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_CONTAINERS_DETAIL_PREPROCESSOR_HPP +#define BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" + +#ifndef BOOST_NO_RVALUE_REFERENCES +#include +#endif + +#include + +#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING +#error "This file is not needed when perfect forwarding is available" +#endif + +#include +#include +#include +#include +#include + +#define BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS 10 + +//Note: +//We define template parameters as const references to +//be able to bind temporaries. After that we will un-const them. +//This cast is ugly but it is necessary until "perfect forwarding" +//is achieved in C++0x. Meanwhile, if we want to be able to +//bind rvalues with non-const references, we have to be ugly +#ifndef BOOST_NO_RVALUE_REFERENCES + #define BOOST_CONTAINERS_PP_PARAM_LIST(z, n, data) \ + BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \ + //! +#else + #define BOOST_CONTAINERS_PP_PARAM_LIST(z, n, data) \ + const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \ + //! +#endif + +#ifndef BOOST_NO_RVALUE_REFERENCES + #define BOOST_CONTAINERS_PARAM(U, u) \ + U && u \ + //! +#else + #define BOOST_CONTAINERS_PARAM(U, u) \ + const U & u \ + //! +#endif + +#ifndef BOOST_NO_RVALUE_REFERENCES + +#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + +#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \ + BOOST_PP_CAT(m_p, n) (boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \ +//! + +#else + +#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \ + BOOST_PP_CAT(m_p, n) (static_cast( BOOST_PP_CAT(p, n) )) \ +//! + +#endif + +#else +#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \ + BOOST_PP_CAT(m_p, n) (const_cast(BOOST_PP_CAT(p, n))) \ +//! +#endif + +#define BOOST_CONTAINERS_AUX_PARAM_INC(z, n, data) \ + BOOST_PP_CAT(++m_p, n) \ +//! + +#ifndef BOOST_NO_RVALUE_REFERENCES + +#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) + +#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data) \ + BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \ +//! + +#else + +#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data) \ + BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \ +//! + +#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) + + +#else +#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data) \ + BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \ +//! +#endif + +#define BOOST_CONTAINERS_PP_PARAM_FORWARD(z, n, data) \ +boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \ +//! + +#if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) + +#define BOOST_CONTAINERS_PP_MEMBER_FORWARD(z, n, data) \ +::boost::container::containers_detail::stored_ref< BOOST_PP_CAT(P, n) >::forward( BOOST_PP_CAT(m_p, n) ) \ +//! + +#else + +#define BOOST_CONTAINERS_PP_MEMBER_FORWARD(z, n, data) \ +boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \ +//! + +#endif //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) + +#define BOOST_CONTAINERS_PP_MEMBER_IT_FORWARD(z, n, data) \ +BOOST_PP_CAT(*m_p, n) \ +//! + +#include + +#else +#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING +#error "This file is not needed when perfect forwarding is available" +#endif +#endif //#ifndef BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP diff --git a/include/boost/container/detail/stored_ref.hpp b/include/boost/container/detail/stored_ref.hpp new file mode 100644 index 0000000..8270e14 --- /dev/null +++ b/include/boost/container/detail/stored_ref.hpp @@ -0,0 +1,92 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-2011. 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_CONTAINERS_DETAIL_STORED_REF_HPP +#define BOOST_CONTAINERS_DETAIL_STORED_REF_HPP + +#include "config_begin.hpp" +#include + +#ifndef BOOST_NO_RVALUE_REFERENCES + +namespace boost{ +namespace container{ +namespace containers_detail{ + +template +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 +struct stored_ref +{ + static const T && forward(const T &t) + #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + { return t; } + #else + { return static_cast(t); } + #endif +}; + +template +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 +struct stored_ref +{ + static const T && forward(const T &t) + #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + { return t; } + #else + { return static_cast(t); } + #endif +}; + +template +struct stored_ref +{ + static const T & forward(const T &t) + { return t; } +}; + +template +struct stored_ref +{ + static T & forward(T &t) + { return t; } +}; + +} //namespace containers_detail{ +} //namespace container{ +} //namespace boost{ + +#else +#error "This header can be included only for compiler with rvalue references" +#endif //BOOST_NO_RVALUE_REFERENCES + +#include + +#endif //BOOST_CONTAINERS_DETAIL_STORED_REF_HPP diff --git a/include/boost/container/detail/transform_iterator.hpp b/include/boost/container/detail/transform_iterator.hpp new file mode 100644 index 0000000..b6176fb --- /dev/null +++ b/include/boost/container/detail/transform_iterator.hpp @@ -0,0 +1,176 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Gennaro Prota 2003 - 2004. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP +#define BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include +#include +#include + +namespace boost { +namespace container { + +template +struct operator_arrow_proxy +{ + operator_arrow_proxy(const PseudoReference &px) + : m_value(px) + {} + + 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; +}; + +template +struct operator_arrow_proxy +{ + operator_arrow_proxy(T &px) + : m_value(px) + {} + + T* operator->() const { return const_cast(&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; +}; + +template +class transform_iterator + : public UnaryFunction + , public std::iterator + < typename Iterator::iterator_category + , typename containers_detail::remove_reference::type + , typename Iterator::difference_type + , operator_arrow_proxy + , typename UnaryFunction::result_type> +{ + public: + explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction()) + : UnaryFunction(f), m_it(it) + {} + + explicit transform_iterator() + : UnaryFunction(), m_it() + {} + + //Constructors + transform_iterator& operator++() + { increment(); return *this; } + + transform_iterator operator++(int) + { + transform_iterator result (*this); + increment(); + return result; + } + + friend bool operator== (const transform_iterator& i, const transform_iterator& i2) + { return i.equal(i2); } + + friend bool operator!= (const transform_iterator& i, const transform_iterator& i2) + { return !(i == i2); } + +/* + friend bool operator> (const transform_iterator& i, const transform_iterator& i2) + { return i2 < i; } + + friend bool operator<= (const transform_iterator& i, const transform_iterator& i2) + { return !(i > i2); } + + friend bool operator>= (const transform_iterator& i, const transform_iterator& i2) + { return !(i < i2); } +*/ + friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2) + { return i2.distance_to(i); } + + //Arithmetic + transform_iterator& operator+=(typename Iterator::difference_type off) + { this->advance(off); return *this; } + + transform_iterator operator+(typename Iterator::difference_type off) const + { + transform_iterator other(*this); + other.advance(off); + return other; + } + + friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right) + { return right + off; } + + transform_iterator& operator-=(typename Iterator::difference_type off) + { this->advance(-off); return *this; } + + transform_iterator operator-(typename Iterator::difference_type off) const + { return *this + (-off); } + + typename UnaryFunction::result_type operator*() const + { return dereference(); } + + operator_arrow_proxy + operator->() const + { return operator_arrow_proxy(dereference()); } + + Iterator & base() + { return m_it; } + + const Iterator & base() const + { return m_it; } + + private: + Iterator m_it; + + void increment() + { ++m_it; } + + void decrement() + { --m_it; } + + bool equal(const transform_iterator &other) const + { return m_it == other.m_it; } + + bool less(const transform_iterator &other) const + { return other.m_it < m_it; } + + typename UnaryFunction::result_type dereference() const + { return UnaryFunction::operator()(*m_it); } + + void advance(typename Iterator::difference_type n) + { std::advance(m_it, n); } + + typename Iterator::difference_type distance_to(const transform_iterator &other)const + { return std::distance(other.m_it, m_it); } +}; + +template +transform_iterator +make_transform_iterator(Iterator it, UnaryFunc fun) +{ + return transform_iterator(it, fun); +} + +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp new file mode 100644 index 0000000..012fb2d --- /dev/null +++ b/include/boost/container/detail/tree.hpp @@ -0,0 +1,1064 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_TREE_HPP +#define BOOST_CONTAINERS_TREE_HPP + +#include "config_begin.hpp" +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING +#include +#endif + +#include //std::pair +#include +#include + +namespace boost { +namespace container { +namespace containers_detail { + +template +struct value_compare_impl + : public KeyCompare +{ + typedef Value value_type; + typedef KeyCompare key_compare; + typedef KeyOfValue key_of_value; + typedef Key key_type; + + value_compare_impl(const key_compare &kcomp) + : key_compare(kcomp) + {} + + const key_compare &key_comp() const + { return static_cast(*this); } + + key_compare &key_comp() + { return static_cast(*this); } + + template + struct is_key + { + static const bool value = is_same::value; + }; + + template + typename enable_if_c::value, const key_type &>::type + key_forward(const T &key) const + { return key; } + + template + typename enable_if_c::value, const key_type &>::type + key_forward(const T &key) const + { return KeyOfValue()(key); } + + template + bool operator()(const KeyType &key1, const KeyType2 &key2) const + { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); } +}; + +template +struct rbtree_hook +{ + typedef typename containers_detail::bi::make_set_base_hook + < containers_detail::bi::void_pointer + , containers_detail::bi::link_mode + , containers_detail::bi::optimize_size + >::type type; +}; + +template +struct rbtree_type +{ + typedef T type; +}; + +template +struct rbtree_type< std::pair > +{ + typedef pair type; +}; + +template +struct rbtree_node + : public rbtree_hook::type +{ + typedef typename rbtree_hook::type hook_type; + + typedef T value_type; + typedef typename rbtree_type::type internal_type; + + typedef rbtree_node node_type; + + #ifndef BOOST_CONTAINERS_PERFECT_FORWARDING + + rbtree_node() + : m_data() + {} + + rbtree_node(const rbtree_node &other) + : m_data(other.m_data) + {} + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + rbtree_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + : m_data(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \ + {} \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #else //#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING + + rbtree_node() + : m_data() + {} + + template + rbtree_node(Args &&...args) + : m_data(boost::forward(args)...) + {} + #endif//#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING + + rbtree_node &operator=(const rbtree_node &other) + { do_assign(other.m_data); return *this; } + + T &get_data() + { + T* ptr = reinterpret_cast(&this->m_data); + return *ptr; + } + + const T &get_data() const + { + const T* ptr = reinterpret_cast(&this->m_data); + return *ptr; + } + + private: + internal_type m_data; + + template + void do_assign(const std::pair &p) + { + const_cast(m_data.first) = p.first; + m_data.second = p.second; + } + + template + void do_assign(const pair &p) + { + const_cast(m_data.first) = p.first; + m_data.second = p.second; + } + + template + void do_assign(const V &v) + { m_data = v; } + + public: + template + static void construct(node_type *ptr, BOOST_FWD_REF(Convertible) convertible) + { new(ptr) node_type(boost::forward(convertible)); } +}; + +}//namespace containers_detail { +#if defined(BOOST_NO_RVALUE_REFERENCES) +template +struct has_own_construct_from_it + < boost::container::containers_detail::rbtree_node > +{ + static const bool value = true; +}; +#endif +namespace containers_detail { + +template +struct intrusive_rbtree_type +{ + typedef typename A::value_type value_type; + typedef typename boost::pointer_to_other + ::type void_pointer; + typedef typename containers_detail::rbtree_node + node_type; + typedef node_compare node_compare_type; + typedef typename containers_detail::bi::make_rbtree + + ,containers_detail::bi::base_hook::type> + ,containers_detail::bi::constant_time_size + ,containers_detail::bi::size_type + >::type container_type; + typedef container_type type ; +}; + +} //namespace containers_detail { + +namespace containers_detail { + +template +class rbtree + : protected containers_detail::node_alloc_holder + + >::type + > +{ + typedef typename containers_detail::intrusive_rbtree_type + + >::type Icont; + typedef containers_detail::node_alloc_holder AllocHolder; + typedef typename AllocHolder::NodePtr NodePtr; + typedef rbtree < Key, Value, KeyOfValue + , KeyCompare, A> ThisType; + typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef typename AllocHolder::ValAlloc ValAlloc; + typedef typename AllocHolder::Node Node; + typedef typename Icont::iterator iiterator; + typedef typename Icont::const_iterator iconst_iterator; + typedef containers_detail::allocator_destroyer Destroyer; + typedef typename AllocHolder::allocator_v1 allocator_v1; + typedef typename AllocHolder::allocator_v2 allocator_v2; + typedef typename AllocHolder::alloc_version alloc_version; + + 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(!m_icont.empty()){ + if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){ + //First recycle a node (this can't throw) + //NodePtr p = m_icont.unlink_leftmost_without_rebalance(); + try{ + //This can throw + *p = other; + 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); + } + } + + AllocHolder &m_holder; + Icont &m_icont; + }; + BOOST_COPYABLE_AND_MOVABLE(rbtree) + + public: + + typedef Key key_type; + typedef Value value_type; + typedef A allocator_type; + typedef KeyCompare key_compare; + typedef value_compare_impl< Key, Value + , KeyCompare, KeyOfValue> value_compare; + typedef typename A::pointer pointer; + typedef typename A::const_pointer const_pointer; + typedef typename A::reference reference; + typedef typename A::const_reference const_reference; + typedef typename A::size_type size_type; + typedef typename 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 NodeAlloc stored_allocator_type; + + private: + + template + struct key_node_compare + : private KeyValueCompare + { + key_node_compare(const KeyValueCompare &comp) + : KeyValueCompare(comp) + {} + + template + struct is_node + { + static const bool value = is_same::value; + }; + + template + typename enable_if_c::value, const value_type &>::type + key_forward(const T &node) const + { return node.get_data(); } + + template + typename enable_if_c::value, const T &>::type + key_forward(const T &key) const + { return key; } + + template + bool operator()(const KeyType &key1, const KeyType2 &key2) const + { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); } + }; + + typedef key_node_compare 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 ; + typedef rbtree_difference_type difference_type; + + //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); } + + //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; } + }; + + //rbtree iterator + class iterator : public const_iterator + { + private: + explicit iterator(iiterator it) + : const_iterator(it) + {} + + iiterator get() + { return this->m_it; } + + public: + friend class rbtree ; + 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 pointer(&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 reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + rbtree(const key_compare& comp = key_compare(), + const allocator_type& a = allocator_type()) + : AllocHolder(a, comp) + {} + + template + rbtree(InputIterator first, InputIterator last, const key_compare& comp, + const allocator_type& a, bool unique_insertion) + : AllocHolder(a, comp) + { + typedef typename std::iterator_traits::iterator_category ItCat; + priv_create_and_insert_nodes(first, last, unique_insertion, alloc_version(), ItCat()); + } + + template + rbtree( ordered_range_t, InputIterator first, InputIterator last + , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()) + : AllocHolder(a, comp) + { + typedef typename std::iterator_traits::iterator_category ItCat; + priv_create_and_insert_ordered_nodes(first, last, alloc_version(), ItCat()); + } + + rbtree(const rbtree& x) + : AllocHolder(x, x.key_comp()) + { + this->icont().clone_from + (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); + } + + rbtree(BOOST_RV_REF(rbtree) x) + : AllocHolder(x, x.key_comp()) + { this->swap(x); } + + ~rbtree() + {} //AllocHolder clears the tree + + rbtree& operator=(BOOST_COPY_ASSIGN_REF(rbtree) x) + { + if (this != &x) { + //Transfer all the nodes to a temporary tree + //If anything goes wrong, all the nodes will be destroyed + //automatically + Icont other_tree(this->icont().value_comp()); + other_tree.swap(this->icont()); + + //Now recreate the source tree reusing nodes stored by other_tree + this->icont().clone_from + (x.icont() + , RecyclingCloner(*this, other_tree) + //, AllocHolder::cloner(*this) + , 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; + } + + rbtree& operator=(BOOST_RV_REF(rbtree) mx) + { this->clear(); this->swap(mx); return *this; } + + public: + // accessors: + value_compare value_comp() const + { return this->icont().value_comp().value_comp(); } + + key_compare key_comp() const + { return this->icont().value_comp().value_comp().key_comp(); } + + allocator_type get_allocator() const + { return allocator_type(this->node_alloc()); } + + const stored_allocator_type &get_stored_allocator() const + { return this->node_alloc(); } + + stored_allocator_type &get_stored_allocator() + { return this->node_alloc(); } + + iterator begin() + { return iterator(this->icont().begin()); } + + const_iterator begin() const + { return this->cbegin(); } + + iterator end() + { return iterator(this->icont().end()); } + + const_iterator end() const + { return this->cend(); } + + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator rbegin() const + { return this->crbegin(); } + + reverse_iterator rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator rend() const + { return this->crend(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return const_iterator(this->non_const_icont().begin()); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return const_iterator(this->non_const_icont().end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const + { return const_reverse_iterator(cend()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return const_reverse_iterator(cbegin()); } + + bool empty() const + { return !this->size(); } + + size_type size() const + { return this->icont().size(); } + + size_type max_size() const + { return AllocHolder::max_size(); } + + void swap(ThisType& x) + { AllocHolder::swap(x); } + + public: + + typedef typename Icont::insert_commit_data insert_commit_data; + + // insert/erase + std::pair insert_unique_check + (const key_type& key, insert_commit_data &data) + { + std::pair ret = + this->icont().insert_unique_check(key, KeyNodeCompare(value_comp()), data); + return std::pair(iterator(ret.first), ret.second); + } + + std::pair insert_unique_check + (const_iterator hint, const key_type& key, insert_commit_data &data) + { + std::pair ret = + this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(value_comp()), data); + return std::pair(iterator(ret.first), ret.second); + } + + 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); + } + + template + iterator insert_unique_commit + (BOOST_FWD_REF(MovableConvertible) mv, insert_commit_data &data) + { + NodePtr tmp = AllocHolder::create_node(boost::forward(mv)); + iiterator it(this->icont().insert_unique_commit(*tmp, data)); + return iterator(it); + } + + std::pair insert_unique(const value_type& v) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(KeyOfValue()(v), data); + if(!ret.second) + return ret; + return std::pair + (this->insert_unique_commit(v, data), true); + } + + template + std::pair insert_unique(BOOST_FWD_REF(MovableConvertible) mv) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(KeyOfValue()(mv), data); + if(!ret.second) + return ret; + return std::pair + (this->insert_unique_commit(boost::forward(mv), data), true); + } + + private: + iterator emplace_unique_impl(NodePtr p) + { + value_type &v = p->get_data(); + insert_commit_data data; + std::pair ret = + this->insert_unique_check(KeyOfValue()(v), data); + if(!ret.second){ + Destroyer(this->node_alloc())(p); + return ret.first; + } + return iterator(iiterator(this->icont().insert_unique_commit(*p, data))); + } + + iterator emplace_unique_hint_impl(const_iterator hint, NodePtr p) + { + value_type &v = p->get_data(); + insert_commit_data data; + std::pair ret = + this->insert_unique_check(hint, KeyOfValue()(v), data); + if(!ret.second){ + Destroyer(this->node_alloc())(p); + return ret.first; + } + return iterator(iiterator(this->icont().insert_unique_commit(*p, data))); + } + + public: + + #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + template + iterator emplace_unique(Args&&... args) + { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward(args)...)); } + + template + iterator emplace_hint_unique(const_iterator hint, Args&&... args) + { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward(args)...)); } + + template + iterator emplace_equal(Args&&... args) + { + NodePtr p(AllocHolder::create_node(boost::forward(args)...)); + return iterator(this->icont().insert_equal(this->icont().end(), *p)); + } + + template + iterator emplace_hint_equal(const_iterator hint, Args&&... args) + { + NodePtr p(AllocHolder::create_node(boost::forward(args)...)); + return iterator(this->icont().insert_equal(hint.get(), *p)); + } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator emplace_unique() + { return this->emplace_unique_impl(AllocHolder::create_node()); } + + iterator emplace_hint_unique(const_iterator hint) + { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node()); } + + iterator emplace_equal() + { + NodePtr p(AllocHolder::create_node()); + return iterator(this->icont().insert_equal(this->icont().end(), *p)); + } + + iterator emplace_hint_equal(const_iterator hint) + { + NodePtr p(AllocHolder::create_node()); + return iterator(this->icont().insert_equal(hint.get(), *p)); + } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + return this->emplace_unique_impl \ + (AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \ + } \ + \ + template \ + iterator emplace_hint_unique(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + return this->emplace_unique_hint_impl \ + (hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \ + } \ + \ + template \ + iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \ + return iterator(this->icont().insert_equal(this->icont().end(), *p)); \ + } \ + \ + template \ + iterator emplace_hint_equal(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \ + return iterator(this->icont().insert_equal(hint.get(), *p)); \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator insert_unique(const_iterator hint, const value_type& v) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(hint, KeyOfValue()(v), data); + if(!ret.second) + return ret.first; + return this->insert_unique_commit(v, data); + } + + template + iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(hint, KeyOfValue()(mv), data); + if(!ret.second) + return ret.first; + return this->insert_unique_commit(boost::forward(mv), data); + } + + template + 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 end(this->end()); + for( ; first != last; ++first) + this->insert_unique(end, *first); + } + else{ + 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)); + } + + template + iterator insert_equal(BOOST_FWD_REF(MovableConvertible) mv) + { + NodePtr p(AllocHolder::create_node(boost::forward(mv))); + return iterator(this->icont().insert_equal(this->icont().end(), *p)); + } + + 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)); + } + + template + iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) + { + NodePtr p(AllocHolder::create_node(boost::forward(mv))); + return iterator(this->icont().insert_equal(hint.get(), *p)); + } + + template + void insert_equal(InputIterator first, InputIterator last) + { + //Insert with end hint, to achieve linear + //complexity if [first, last) is ordered + const_iterator end(this->cend()); + for( ; first != last; ++first) + this->insert_equal(end, *first); + } + + iterator erase(const_iterator position) + { return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc()))); } + + size_type erase(const key_type& k) + { return AllocHolder::erase_key(k, KeyNodeCompare(value_comp()), alloc_version()); } + + iterator erase(const_iterator first, const_iterator last) + { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); } + + void clear() + { AllocHolder::clear(alloc_version()); } + + // set operations: + iterator find(const key_type& k) + { return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); } + + const_iterator find(const key_type& k) const + { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(value_comp()))); } + + size_type count(const key_type& k) const + { return size_type(this->icont().count(k, KeyNodeCompare(value_comp()))); } + + iterator lower_bound(const key_type& k) + { return iterator(this->icont().lower_bound(k, KeyNodeCompare(value_comp()))); } + + const_iterator lower_bound(const key_type& k) const + { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(value_comp()))); } + + iterator upper_bound(const key_type& k) + { return iterator(this->icont().upper_bound(k, KeyNodeCompare(value_comp()))); } + + const_iterator upper_bound(const key_type& k) const + { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); } + + std::pair equal_range(const key_type& k) + { + std::pair ret = + this->icont().equal_range(k, KeyNodeCompare(value_comp())); + return std::pair(iterator(ret.first), iterator(ret.second)); + } + + std::pair equal_range(const key_type& k) const + { + std::pair ret = + this->non_const_icont().equal_range(k, KeyNodeCompare(value_comp())); + return std::pair + (const_iterator(ret.first), const_iterator(ret.second)); + } + + private: + //Iterator range version + template + void priv_create_and_insert_nodes + (InpIterator beg, InpIterator end, bool unique, allocator_v1, std::input_iterator_tag) + { + if(unique){ + for (; beg != end; ++beg){ + this->insert_unique(*beg); + } + } + else{ + for (; beg != end; ++beg){ + this->insert_equal(*beg); + } + } + } + + template + 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()); + } + + 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 + void priv_create_and_insert_nodes + (FwdIterator beg, FwdIterator end, bool unique, allocator_v2, std::forward_iterator_tag) + { + 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())); + } + } + } + + //Iterator range version + template + 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); + } + } + + template + 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()); + } + + class back_insertion_functor; + friend class back_insertion_functor; + + class back_insertion_functor + { + Icont &icont_; + + public: + back_insertion_functor(Icont &icont) + : icont_(icont) + {} + + void operator()(Node &n) + { this->icont_.push_back(n); } + }; + + + template + 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())); + } + } +}; + +template +inline bool +operator==(const rbtree& x, + const rbtree& y) +{ + return x.size() == y.size() && + std::equal(x.begin(), x.end(), y.begin()); +} + +template +inline bool +operator<(const rbtree& x, + const rbtree& y) +{ + return std::lexicographical_compare(x.begin(), x.end(), + y.begin(), y.end()); +} + +template +inline bool +operator!=(const rbtree& x, + const rbtree& y) { + return !(x == y); +} + +template +inline bool +operator>(const rbtree& x, + const rbtree& y) { + return y < x; +} + +template +inline bool +operator<=(const rbtree& x, + const rbtree& y) { + return !(y < x); +} + +template +inline bool +operator>=(const rbtree& x, + const rbtree& y) { + return !(x < y); +} + + +template +inline void +swap(rbtree& x, + rbtree& y) +{ + x.swap(y); +} + +} //namespace containers_detail { +} //namespace container { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move + > +{ + static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; +}; +*/ +} //namespace boost { + +#include + +#endif //BOOST_CONTAINERS_TREE_HPP diff --git a/include/boost/container/detail/type_traits.hpp b/include/boost/container/detail/type_traits.hpp new file mode 100644 index 0000000..28095ba --- /dev/null +++ b/include/boost/container/detail/type_traits.hpp @@ -0,0 +1,203 @@ +////////////////////////////////////////////////////////////////////////////// +// (C) Copyright John Maddock 2000. +// (C) Copyright Ion Gaztanaga 2005-2011. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +// The alignment_of implementation comes from John Maddock's boost::alignment_of code +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP +#define BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" + +#include + +namespace boost { +namespace container { +namespace containers_detail { + +struct nat{}; + +//boost::alignment_of yields to 10K lines of preprocessed code, so we +//need an alternative +template struct alignment_of; + +template +struct alignment_of_hack +{ + char c; + T t; + alignment_of_hack(); +}; + +template +struct alignment_logic +{ + enum{ value = A < S ? A : S }; +}; + +template< typename T > +struct alignment_of +{ + enum{ value = alignment_logic + < sizeof(alignment_of_hack) - sizeof(T) + , sizeof(T)>::value }; +}; + +//This is not standard, but should work with all compilers +union max_align +{ + char char_; + short short_; + int int_; + long long_; + #ifdef BOOST_HAS_LONG_LONG + long long long_long_; + #endif + float float_; + double double_; + long double long_double_; + void * void_ptr_; +}; + +template +struct remove_reference +{ + typedef T type; +}; + +template +struct remove_reference +{ + typedef T type; +}; + +#ifndef BOOST_NO_RVALUE_REFERENCES + +template +struct remove_reference +{ + typedef T type; +}; + +#else + +template +struct remove_reference< ::boost::rv > +{ + typedef T type; +}; + +#endif + +template +struct is_reference +{ + enum { value = false }; +}; + +template +struct is_reference +{ + enum { value = true }; +}; + +template +struct is_pointer +{ + enum { value = false }; +}; + +template +struct is_pointer +{ + enum { value = true }; +}; + +template +struct add_reference +{ + typedef T& type; +}; + +template +struct add_reference +{ + typedef T& type; +}; + +template<> +struct add_reference +{ + typedef nat &type; +}; + +template<> +struct add_reference +{ + typedef const nat &type; +}; + +template +struct add_const_reference +{ typedef const T &type; }; + +template +struct add_const_reference +{ typedef T& type; }; + +template +struct is_same +{ + typedef char yes_type; + struct no_type + { + char padding[8]; + }; + + template + static yes_type is_same_tester(V*, V*); + static no_type is_same_tester(...); + + static T *t; + static U *u; + + static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u)); +}; + +template +struct remove_const +{ + typedef T type; +}; + +template +struct remove_const< const T> +{ + typedef T type; +}; + +template +struct remove_ref_const +{ + typedef typename remove_const< typename remove_reference::type >::type type; +}; + +} // namespace containers_detail +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP diff --git a/include/boost/container/detail/utilities.hpp b/include/boost/container/detail/utilities.hpp new file mode 100644 index 0000000..78e9ccd --- /dev/null +++ b/include/boost/container/detail/utilities.hpp @@ -0,0 +1,150 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_DETAIL_UTILITIES_HPP +#define BOOST_CONTAINERS_DETAIL_UTILITIES_HPP + +#include "config_begin.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace container { +namespace containers_detail { + +template +const T &max_value(const T &a, const T &b) +{ return a > b ? a : b; } + +template +const T &min_value(const T &a, const T &b) +{ return a < b ? a : b; } + +template +SizeType + get_next_capacity(const SizeType max_size + ,const SizeType capacity + ,const SizeType n) +{ +// if (n > max_size - capacity) +// throw std::length_error("get_next_capacity"); + + const SizeType m3 = max_size/3; + + if (capacity < m3) + return capacity + max_value(3*(capacity+1)/5, n); + + if (capacity < m3*2) + return capacity + max_value((capacity+1)/2, n); + + return max_size; +} + +template +struct smart_ptr_type +{ + typedef typename SmartPtr::value_type value_type; + typedef value_type *pointer; + static pointer get (const SmartPtr &smartptr) + { return smartptr.get();} +}; + +template +struct smart_ptr_type +{ + typedef T value_type; + typedef value_type *pointer; + static pointer get (pointer ptr) + { return ptr;} +}; + +//!Overload for smart pointers to avoid ADL problems with get_pointer +template +inline typename smart_ptr_type::pointer +get_pointer(const Ptr &ptr) +{ return smart_ptr_type::get(ptr); } + +//!To avoid ADL problems with swap +template +inline void do_swap(T& x, T& y) +{ + using std::swap; + swap(x, y); +} + +//Rounds "orig_size" by excess to round_to bytes +template +inline SizeType get_rounded_size(SizeType orig_size, SizeType round_to) +{ + return ((orig_size-1)/round_to+1)*round_to; +} + +template +struct ct_rounded_size +{ + enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo }; +}; + +template +struct __rw_is_enum +{ +struct _C_no { }; +struct _C_yes { int _C_dummy [2]; }; + +struct _C_indirect { +// prevent classes with user-defined conversions from matching + +// use double to prevent float->int gcc conversion warnings +_C_indirect (double); +}; + +// 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); + +static _TypeT _C_make_T (); +}; + +enum { +_C_val = sizeof (_C_yes) +== sizeof (_C_nest::_C_is (0, _C_nest::_C_make_T ())) +&& !::boost::is_fundamental<_TypeT>::value +}; + +}; + +template +struct move_const_ref_type + : if_c +// < ::boost::is_fundamental::value || ::boost::is_pointer::value || ::boost::is_member_pointer::value || ::boost::is_enum::value + < !::boost::is_class::value + ,const T & + ,BOOST_CATCH_CONST_RLVALUE(T) + > +{}; + +} //namespace containers_detail { +} //namespace container { +} //namespace boost { + + +#include + +#endif //#ifndef BOOST_CONTAINERS_DETAIL_UTILITIES_HPP diff --git a/include/boost/container/detail/value_init.hpp b/include/boost/container/detail/value_init.hpp new file mode 100644 index 0000000..5145fe9 --- /dev/null +++ b/include/boost/container/detail/value_init.hpp @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. +// +// 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_CONTAINERS_DETAIL_VALUE_INIT_HPP +#define BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include + +namespace boost { +namespace container { +namespace containers_detail { + +template +struct value_init +{ + value_init() + : m_t() + {} + + T m_t; +}; + +} //namespace containers_detail { +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP diff --git a/include/boost/container/detail/variadic_templates_tools.hpp b/include/boost/container/detail/variadic_templates_tools.hpp new file mode 100644 index 0000000..c16992e --- /dev/null +++ b/include/boost/container/detail/variadic_templates_tools.hpp @@ -0,0 +1,153 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-2011. 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_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP +#define BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include "config_begin.hpp" +#include +#include +#include //std::size_t + +namespace boost { +namespace container { +namespace containers_detail { + +template +class tuple; + +template<> class tuple<> +{}; + +template +class tuple + : private tuple +{ + typedef tuple inherited; + + public: + tuple() { } + + // implicit copy-constructor is okay + // Construct tuple from separate arguments. + tuple(typename add_const_reference::type v, + typename add_const_reference::type... vtail) + : inherited(vtail...), m_head(v) + {} + + // Construct tuple from another tuple. + template + tuple(const tuple& other) + : m_head(other.head()), inherited(other.tail()) + {} + + template + tuple& operator=(const tuple& other) + { + m_head = other.head(); + tail() = other.tail(); + return this; + } + + typename add_reference::type head() { return m_head; } + typename add_reference::type head() const { return m_head; } + + inherited& tail() { return *this; } + const inherited& tail() const { return *this; } + + protected: + Head m_head; +}; + + +template +tuple tie_forward(Values&&... values) +{ return tuple(values...); } + +template +struct tuple_element; + +template +struct tuple_element > +{ + typedef typename tuple_element >::type type; +}; + +template +struct tuple_element<0, tuple > +{ + typedef Head type; +}; + +template +class get_impl; + +template +class get_impl > +{ + typedef typename tuple_element >::type Element; + typedef get_impl > Next; + + public: + typedef typename add_reference::type type; + typedef typename add_const_reference::type const_type; + static type get(tuple& t) { return Next::get(t.tail()); } + static const_type get(const tuple& t) { return Next::get(t.tail()); } +}; + +template +class get_impl<0, tuple > +{ + public: + typedef typename add_reference::type type; + typedef typename add_const_reference::type const_type; + static type get(tuple& t) { return t.head(); } + static const_type get(const tuple& t){ return t.head(); } +}; + +template +typename get_impl >::type get(tuple& t) +{ return get_impl >::get(t); } + +template +typename get_impl >::const_type get(const tuple& t) +{ return get_impl >::get(t); } + +//////////////////////////////////////////////////// +// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will +// be used to "unpack" into comma-separated values +// in a function call. +//////////////////////////////////////////////////// + +template +struct index_tuple{}; + +template > +struct build_number_seq; + +template +struct build_number_seq > + : build_number_seq > +{}; + +template +struct build_number_seq<0, index_tuple > +{ typedef index_tuple type; }; + + +}}} //namespace boost { namespace container { namespace containers_detail { + +#include + +#endif //#ifndef BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP diff --git a/include/boost/container/detail/version_type.hpp b/include/boost/container/detail/version_type.hpp new file mode 100644 index 0000000..a194342 --- /dev/null +++ b/include/boost/container/detail/version_type.hpp @@ -0,0 +1,92 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This code comes from N1953 document by Howard E. Hinnant +// +////////////////////////////////////////////////////////////////////////////// + + +#ifndef BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP +#define BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP + +#include "config_begin.hpp" + +#include +#include + +namespace boost{ +namespace container { +namespace containers_detail { + +//using namespace boost; + +template +struct version_type + : public containers_detail::integral_constant +{ + typedef T type; + + version_type(const version_type&); +}; + +namespace impl{ + +template , typename T::version>::value> +struct extract_version +{ + static const unsigned value = 1; +}; + +template +struct extract_version +{ + static const unsigned value = T::version::value; +}; + +template +struct has_version +{ + private: + struct two {char _[2];}; + template static two test(...); + template static char test(const typename U::version*); + public: + static const bool value = sizeof(test(0)) == 1; + void dummy(){} +}; + +template ::value> +struct version +{ + static const unsigned value = 1; +}; + +template +struct version +{ + static const unsigned value = extract_version::value; +}; + +} //namespace impl + +template +struct version + : public containers_detail::integral_constant::value> +{ +}; + +} //namespace containers_detail { +} //namespace container { +} //namespace boost{ + +#include "config_end.hpp" + +#endif //#define BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp new file mode 100644 index 0000000..2846590 --- /dev/null +++ b/include/boost/container/detail/workaround.hpp @@ -0,0 +1,24 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_DETAIL_WORKAROUND_HPP +#define BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP + +#include "config_begin.hpp" + +#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)\ + && !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL) +#define BOOST_CONTAINERS_PERFECT_FORWARDING + +#endif + +#include + +#endif //#ifndef BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp new file mode 100644 index 0000000..c637ef5 --- /dev/null +++ b/include/boost/container/flat_map.hpp @@ -0,0 +1,1443 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_FLAT_MAP_HPP +#define BOOST_CONTAINERS_FLAT_MAP_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 A = std::allocator > +#else +template +#endif +class flat_map; + +template +inline bool operator==(const flat_map& x, + const flat_map& y); + +template +inline bool operator<(const flat_map& x, + const flat_map& y); +/// @endcond + +//! A flat_map is a kind of associative container that supports unique keys (contains at +//! most one of each key value) and provides for fast retrieval of values of another +//! type T based on the keys. The flat_map class supports random-access iterators. +//! +//! A flat_map satisfies all of the requirements of a container and of a reversible +//! container and of an associative container. A flat_map also provides +//! most operations described for unique keys. For a +//! flat_map the key_type is Key and the value_type is std::pair +//! (unlike std::map which value_type is std::pair<const Key, T>). +//! +//! Pred is the ordering function for Keys (e.g. std::less). +//! +//! A is the allocator to allocate the value_types +//! (e.g. allocator< std::pair >). +//! +//! 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 +//! pointing to elements that come after (their keys are bigger) the erased element. +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template >, class A = std::allocator > +#else +template +#endif +class flat_map +{ + /// @cond + private: + BOOST_COPYABLE_AND_MOVABLE(flat_map) + //This is the tree that we should store if pair was movable + typedef containers_detail::flat_tree, + containers_detail::select1st< std::pair >, + Pred, + A> tree_t; + + //This is the real tree stored here. It's based on a movable pair + typedef containers_detail::flat_tree, + containers_detail::select1st >, + Pred, + typename A::template + rebind >::other> 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; + + template + static D &force(const S &s) + { return *const_cast(reinterpret_cast(&s)); } + + template + static D force_copy(S s) + { + value_type *vp = reinterpret_cast(&*s); + return D(vp); + } + + /// @endcond + + public: + + // typedefs: + typedef typename impl_tree_t::key_type key_type; + typedef T mapped_type; + typedef typename std::pair value_type; + typedef typename A::pointer pointer; + typedef typename A::const_pointer const_pointer; + typedef typename A::reference reference; + typedef typename A::const_reference const_reference; + typedef containers_detail::flat_tree_value_compare + < Pred + , containers_detail::select1st< std::pair > + , std::pair > value_compare; + typedef Pred key_compare; + typedef typename containers_detail:: + get_flat_tree_iterators::iterator iterator; + typedef typename containers_detail:: + get_flat_tree_iterators::const_iterator const_iterator; + typedef typename containers_detail:: + get_flat_tree_iterators + ::reverse_iterator reverse_iterator; + typedef typename containers_detail:: + get_flat_tree_iterators + ::const_reverse_iterator const_reverse_iterator; + typedef typename impl_tree_t::size_type size_type; + typedef typename impl_tree_t::difference_type difference_type; + typedef A allocator_type; + typedef A stored_allocator_type; + + //! Effects: Constructs an empty flat_map using the specified + //! comparison object and allocator. + //! + //! Complexity: Constant. + explicit flat_map(const Pred& comp = Pred(), const allocator_type& a = allocator_type()) + : m_flat_tree(comp, force(a)) {} + + //! Effects: Constructs an empty flat_map using the specified comparison object and + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + flat_map(InputIterator first, InputIterator last, const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, force(a)) + { m_flat_tree.insert_unique(first, last); } + + //! Effects: Constructs an empty flat_map using the specified comparison object and + //! allocator, and inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! Complexity: Linear in N. + template + flat_map( ordered_unique_range_t, InputIterator first, InputIterator last + , const Pred& comp = Pred(), const allocator_type& a = allocator_type()) + : m_flat_tree(ordered_range, first, last, comp, a) + {} + + //! Effects: Copy constructs a flat_map. + //! + //! Complexity: Linear in x.size(). + flat_map(const flat_map& x) + : m_flat_tree(x.m_flat_tree) {} + + //! Effects: Move constructs a flat_map. + //! Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + flat_map(BOOST_RV_REF(flat_map) x) + : m_flat_tree(boost::move(x.m_flat_tree)) + {} + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + flat_map& operator=(BOOST_COPY_ASSIGN_REF(flat_map) x) + { m_flat_tree = x.m_flat_tree; return *this; } + + //! Effects: Move constructs a flat_map. + //! Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + flat_map& operator=(BOOST_RV_REF(flat_map) mx) + { m_flat_tree = boost::move(mx.m_flat_tree); return *this; } + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return force(m_flat_tree.key_comp()); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return value_compare(force(m_flat_tree.key_comp())); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return force(m_flat_tree.get_allocator()); } + + const stored_allocator_type &get_stored_allocator() const + { return force(m_flat_tree.get_stored_allocator()); } + + stored_allocator_type &get_stored_allocator() + { return force(m_flat_tree.get_stored_allocator()); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return force_copy(m_flat_tree.begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return force(m_flat_tree.begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return force(m_flat_tree.cbegin()); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return force_copy(m_flat_tree.end()); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return force(m_flat_tree.end()); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return force(m_flat_tree.cend()); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return force(m_flat_tree.rbegin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return force(m_flat_tree.rbegin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const + { return force(m_flat_tree.crbegin()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return force(m_flat_tree.rend()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return force(m_flat_tree.rend()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return force(m_flat_tree.crend()); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_flat_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_flat_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_flat_tree.max_size(); } + + //! Effects: If there is no key equivalent to x in the flat_map, inserts + //! value_type(x, T()) into the flat_map. + //! + //! Returns: A reference to the mapped_type corresponding to x in *this. + //! + //! Complexity: Logarithmic. + T &operator[](const key_type& k) + { + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)) + i = insert(i, value_type(k, T())); + return (*i).second; + } + + //! Effects: If there is no key equivalent to x in the flat_map, inserts + //! value_type(move(x), T()) into the flat_map (the key is move-constructed) + //! + //! Returns: A reference to the mapped_type corresponding to x in *this. + //! + //! Complexity: Logarithmic. + T &operator[](BOOST_RV_REF(key_type) mk) + { + key_type &k = mk; + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)) + i = insert(i, value_type(boost::move(k), boost::move(T()))); + return (*i).second; + } + + //! Returns: A reference to the element whose key is equivalent to x. + //! Throws: An exception object of type out_of_range if no such element is present. + //! Complexity: logarithmic. + T& at(const key_type& k) + { + iterator i = this->find(k); + if(i == this->end()){ + throw std::out_of_range("key not found"); + } + return i->second; + } + + //! Returns: A reference to the element whose key is equivalent to x. + //! Throws: An exception object of type out_of_range if no such element is present. + //! Complexity: logarithmic. + const T& at(const key_type& k) const + { + const_iterator i = this->find(k); + if(i == this->end()){ + throw std::out_of_range("key not found"); + } + return i->second; + } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(flat_map& x) + { m_flat_tree.swap(x.m_flat_tree); } + + //! Effects: Inserts x if and only if there is no element in the container + //! with key equivalent to the key of x. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + std::pair insert(const value_type& x) + { return force >( + m_flat_tree.insert_unique(force(x))); } + + //! Effects: 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. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + std::pair insert(BOOST_RV_REF(value_type) x) + { return force >( + m_flat_tree.insert_unique(boost::move(force(x)))); } + + //! Effects: 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. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + std::pair insert(BOOST_RV_REF(impl_value_type) x) + { + return force > + (m_flat_tree.insert_unique(boost::move(x))); + } + + //! Effects: 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. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(const_iterator position, const value_type& x) + { return force_copy( + m_flat_tree.insert_unique(force(position), force(x))); } + + //! Effects: Inserts an element move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(const_iterator position, BOOST_RV_REF(value_type) x) + { return force_copy( + m_flat_tree.insert_unique(force(position), boost::move(force(x)))); } + + //! Effects: Inserts an element move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(const_iterator position, BOOST_RV_REF(impl_value_type) x) + { + return force_copy( + m_flat_tree.insert_unique(force(position), boost::move(x))); + } + + //! Requires: first, last are not iterators into *this. + //! + //! Effects: inserts each element from the range [first,last) if and only + //! if there is no element with key equivalent to the key of that element. + //! + //! Complexity: At most N log(size()+N) (N is the distance from first to last) + //! search time plus N*size() insertion time. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + void insert(InputIterator first, InputIterator last) + { m_flat_tree.insert_unique(first, last); } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... if and only if there is no element in the container + //! with key equivalent to the key of x. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + iterator emplace(Args&&... args) + { return force_copy(m_flat_tree.emplace_unique(boost::forward(args)...)); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(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. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + iterator emplace_hint(const_iterator hint, Args&&... args) + { return force_copy(m_flat_tree.emplace_hint_unique(force(hint), boost::forward(args)...)); } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator emplace() + { return force_copy(m_flat_tree.emplace_unique()); } + + iterator emplace_hint(const_iterator hint) + { return force_copy(m_flat_tree.emplace_hint_unique(force(hint))); } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + return force_copy(m_flat_tree.emplace_unique \ + (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \ + } \ + \ + template \ + iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + return force_copy(m_flat_tree.emplace_hint_unique \ + (force(hint), \ + BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Linear to the elements with keys bigger than position + //! + //! Note: Invalidates elements with keys + //! not less than the erased element. + iterator erase(const_iterator position) + { return force_copy(m_flat_tree.erase(force(position))); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: 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); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: size()*N where N is the distance from first to last. + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + iterator erase(const_iterator first, const_iterator last) + { return force_copy(m_flat_tree.erase(force(first), force(last))); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_flat_tree.clear(); } + + //! Effects: Tries to deallocate the excess of memory created + // with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { m_flat_tree.shrink_to_fit(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return force_copy(m_flat_tree.find(x)); } + + //! Returns: A const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic.s + const_iterator find(const key_type& x) const + { return force(m_flat_tree.find(x)); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_flat_tree.find(x) == m_flat_tree.end() ? 0 : 1; } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return force_copy(m_flat_tree.lower_bound(x)); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return force(m_flat_tree.lower_bound(x)); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return force_copy(m_flat_tree.upper_bound(x)); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return force(m_flat_tree.upper_bound(x)); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) + { return force >(m_flat_tree.equal_range(x)); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) const + { return force >(m_flat_tree.equal_range(x)); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return m_flat_tree.capacity(); } + + //! Effects: 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. + //! + //! Throws: If memory allocation allocation throws or T's copy constructor throws. + //! + //! Note: 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 + friend bool operator== (const flat_map&, + const flat_map&); + template + friend bool operator< (const flat_map&, + const flat_map&); + /// @endcond +}; + +template +inline bool operator==(const flat_map& x, + const flat_map& y) + { return x.m_flat_tree == y.m_flat_tree; } + +template +inline bool operator<(const flat_map& x, + const flat_map& y) + { return x.m_flat_tree < y.m_flat_tree; } + +template +inline bool operator!=(const flat_map& x, + const flat_map& y) + { return !(x == y); } + +template +inline bool operator>(const flat_map& x, + const flat_map& y) + { return y < x; } + +template +inline bool operator<=(const flat_map& x, + const flat_map& y) + { return !(y < x); } + +template +inline bool operator>=(const flat_map& x, + const flat_map& y) + { return !(x < y); } + +template +inline void swap(flat_map& x, + flat_map& y) + { x.swap(y); } + +/// @cond + +} //namespace container { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; +}; +*/ +namespace container { + +// Forward declaration of operators < and ==, needed for friend declaration. +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template >, class A = std::allocator > +#else +template +#endif +class flat_multimap; + +template +inline bool operator==(const flat_multimap& x, + const flat_multimap& y); + +template +inline bool operator<(const flat_multimap& x, + const flat_multimap& y); +/// @endcond + +//! A flat_multimap is a kind of associative container that supports equivalent keys +//! (possibly containing multiple copies of the same key value) and provides for +//! fast retrieval of values of another type T based on the keys. The flat_multimap +//! class supports random-access iterators. +//! +//! A flat_multimap satisfies all of the requirements of a container and of a reversible +//! container and of an associative container. For a +//! flat_multimap the key_type is Key and the value_type is std::pair +//! (unlike std::multimap which value_type is std::pair<const Key, T>). +//! +//! Pred is the ordering function for Keys (e.g. std::less). +//! +//! A is the allocator to allocate the value_types +//! (e.g. allocator< std::pair >). +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template >, class A = std::allocator > +#else +template +#endif +class flat_multimap +{ + /// @cond + private: + BOOST_COPYABLE_AND_MOVABLE(flat_multimap) + typedef containers_detail::flat_tree, + containers_detail::select1st< std::pair >, + Pred, + A> tree_t; + //This is the real tree stored here. It's based on a movable pair + typedef containers_detail::flat_tree, + containers_detail::select1st >, + Pred, + typename A::template + rebind >::other> 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; + + template + static D &force(const S &s) + { return *const_cast((reinterpret_cast(&s))); } + + template + static D force_copy(S s) + { + value_type *vp = reinterpret_cast(&*s); + return D(vp); + } + /// @endcond + + public: + + // typedefs: + typedef typename impl_tree_t::key_type key_type; + typedef T mapped_type; + typedef typename std::pair value_type; + typedef typename A::pointer pointer; + typedef typename A::const_pointer const_pointer; + typedef typename A::reference reference; + typedef typename A::const_reference const_reference; + typedef containers_detail::flat_tree_value_compare + < Pred + , containers_detail::select1st< std::pair > + , std::pair > value_compare; + typedef Pred key_compare; + typedef typename containers_detail:: + get_flat_tree_iterators::iterator iterator; + typedef typename containers_detail:: + get_flat_tree_iterators::const_iterator const_iterator; + typedef typename containers_detail:: + get_flat_tree_iterators + ::reverse_iterator reverse_iterator; + typedef typename containers_detail:: + get_flat_tree_iterators + ::const_reverse_iterator const_reverse_iterator; + typedef typename impl_tree_t::size_type size_type; + typedef typename impl_tree_t::difference_type difference_type; + typedef A allocator_type; + typedef A stored_allocator_type; + + //! Effects: Constructs an empty flat_multimap using the specified comparison + //! object and allocator. + //! + //! Complexity: Constant. + explicit flat_multimap(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, force(a)) { } + + //! Effects: Constructs an empty flat_multimap using the specified comparison object + //! and allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + flat_multimap(InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, force(a)) + { m_flat_tree.insert_equal(first, last); } + + //! Effects: Constructs an empty flat_multimap using the specified comparison object and + //! allocator, and inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate. + //! + //! Complexity: Linear in N. + template + flat_multimap(ordered_range_t, InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(ordered_range, first, last, comp, a) + {} + + //! Effects: Copy constructs a flat_multimap. + //! + //! Complexity: Linear in x.size(). + flat_multimap(const flat_multimap& x) + : m_flat_tree(x.m_flat_tree) { } + + //! Effects: Move constructs a flat_multimap. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + flat_multimap(BOOST_RV_REF(flat_multimap) x) + : m_flat_tree(boost::move(x.m_flat_tree)) + { } + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + flat_multimap& operator=(BOOST_COPY_ASSIGN_REF(flat_multimap) x) + { m_flat_tree = x.m_flat_tree; return *this; } + + //! Effects: this->swap(x.get()). + //! + //! Complexity: Constant. + flat_multimap& operator=(BOOST_RV_REF(flat_multimap) mx) + { m_flat_tree = boost::move(mx.m_flat_tree); return *this; } + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return force(m_flat_tree.key_comp()); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return value_compare(force(m_flat_tree.key_comp())); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return force(m_flat_tree.get_allocator()); } + + const stored_allocator_type &get_stored_allocator() const + { return force(m_flat_tree.get_stored_allocator()); } + + stored_allocator_type &get_stored_allocator() + { return force(m_flat_tree.get_stored_allocator()); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return force_copy(m_flat_tree.begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return force(m_flat_tree.begin()); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return force_copy(m_flat_tree.end()); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return force(m_flat_tree.end()); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return force(m_flat_tree.rbegin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return force(m_flat_tree.rbegin()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return force(m_flat_tree.rend()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return force(m_flat_tree.rend()); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_flat_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_flat_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_flat_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(flat_multimap& x) + { m_flat_tree.swap(x.m_flat_tree); } + + //! Effects: Inserts x and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(const value_type& x) + { return force_copy(m_flat_tree.insert_equal(force(x))); } + + //! Effects: Inserts a new value move-constructed from x and returns + //! the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(BOOST_RV_REF(value_type) x) + { return force_copy(m_flat_tree.insert_equal(boost::move(x))); } + + //! Effects: Inserts a new value move-constructed from x and returns + //! the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(BOOST_RV_REF(impl_value_type) x) + { return force_copy(m_flat_tree.insert_equal(boost::move(x))); } + + //! Effects: Inserts a copy of x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(const_iterator position, const value_type& x) + { return force_copy(m_flat_tree.insert_equal(force(position), force(x))); } + + //! Effects: Inserts a value move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(const_iterator position, BOOST_RV_REF(value_type) x) + { + return force_copy + (m_flat_tree.insert_equal(force(position) + , boost::move(x))); + } + + //! Effects: Inserts a value move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(const_iterator position, BOOST_RV_REF(impl_value_type) x) + { + return force_copy( + m_flat_tree.insert_equal(force(position), boost::move(x))); + } + + //! Requires: first, last are not iterators into *this. + //! + //! Effects: inserts each element from the range [first,last) . + //! + //! Complexity: At most N log(size()+N) (N is the distance from first to last) + //! search time plus N*size() insertion time. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + void insert(InputIterator first, InputIterator last) + { m_flat_tree.insert_equal(first, last); } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + iterator emplace(Args&&... args) + { return force_copy(m_flat_tree.emplace_equal(boost::forward(args)...)); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + iterator emplace_hint(const_iterator hint, Args&&... args) + { + return force_copy(m_flat_tree.emplace_hint_equal + (force(hint), boost::forward(args)...)); + } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator emplace() + { return force_copy(m_flat_tree.emplace_equal()); } + + iterator emplace_hint(const_iterator hint) + { return force_copy(m_flat_tree.emplace_hint_equal(force(hint))); } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + return force_copy(m_flat_tree.emplace_equal \ + (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \ + } \ + \ + template \ + iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + return force_copy(m_flat_tree.emplace_hint_equal \ + (force(hint), \ + BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Linear to the elements with keys bigger than position + //! + //! Note: Invalidates elements with keys + //! not less than the erased element. + iterator erase(const_iterator position) + { return force_copy(m_flat_tree.erase(force(position))); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: 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); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: size()*N where N is the distance from first to last. + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + iterator erase(const_iterator first, const_iterator last) + { return force_copy(m_flat_tree.erase(force(first), force(last))); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_flat_tree.clear(); } + + //! Effects: Tries to deallocate the excess of memory created + // with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { m_flat_tree.shrink_to_fit(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return force_copy(m_flat_tree.find(x)); } + + //! Returns: An const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + const_iterator find(const key_type& x) const + { return force(m_flat_tree.find(x)); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_flat_tree.count(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + {return force_copy(m_flat_tree.lower_bound(x)); } + + //! Returns: A const iterator pointing to the first element with key + //! not less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return force(m_flat_tree.lower_bound(x)); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + {return force_copy(m_flat_tree.upper_bound(x)); } + + //! Returns: A const iterator pointing to the first element with key + //! not less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return force(m_flat_tree.upper_bound(x)); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) + { return force_copy >(m_flat_tree.equal_range(x)); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return force_copy >(m_flat_tree.equal_range(x)); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return m_flat_tree.capacity(); } + + //! Effects: 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. + //! + //! Throws: If memory allocation allocation throws or T's copy constructor throws. + //! + //! Note: 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 + friend bool operator== (const flat_multimap& x, + const flat_multimap& y); + + template + friend bool operator< (const flat_multimap& x, + const flat_multimap& y); + /// @endcond +}; + +template +inline bool operator==(const flat_multimap& x, + const flat_multimap& y) + { return x.m_flat_tree == y.m_flat_tree; } + +template +inline bool operator<(const flat_multimap& x, + const flat_multimap& y) + { return x.m_flat_tree < y.m_flat_tree; } + +template +inline bool operator!=(const flat_multimap& x, + const flat_multimap& y) + { return !(x == y); } + +template +inline bool operator>(const flat_multimap& x, + const flat_multimap& y) + { return y < x; } + +template +inline bool operator<=(const flat_multimap& x, + const flat_multimap& y) + { return !(y < x); } + +template +inline bool operator>=(const flat_multimap& x, + const flat_multimap& y) + { return !(x < y); } + +template +inline void swap(flat_multimap& x, flat_multimap& y) + { x.swap(y); } + +}} + +/// @cond + +namespace boost { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move< boost::container::flat_multimap > +{ + static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; +}; +*/ +} //namespace boost { + +/// @endcond + +#include + +#endif /* BOOST_CONTAINERS_FLAT_MAP_HPP */ diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp new file mode 100644 index 0000000..694a072 --- /dev/null +++ b/include/boost/container/flat_set.hpp @@ -0,0 +1,1261 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_FLAT_SET_HPP +#define BOOST_CONTAINERS_FLAT_SET_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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. + +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template , class A = std::allocator > +#else +template +#endif +class flat_set; + +template +inline bool operator==(const flat_set& x, + const flat_set& y); + +template +inline bool operator<(const flat_set& x, + const flat_set& 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. +//! +//! 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 +//! previous iterators and references +//! +//! Erasing an element of a flat_set invalidates iterators and references +//! pointing to elements that come after (their keys are bigger) the erased element. +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template , class A = std::allocator > +#else +template +#endif +class flat_set +{ + /// @cond + private: + BOOST_COPYABLE_AND_MOVABLE(flat_set) + typedef containers_detail::flat_tree, Pred, A> tree_t; + tree_t m_flat_tree; // flat tree representing flat_set + typedef typename containers_detail:: + move_const_ref_type::type insert_const_ref_type; + /// @endcond + + 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; + + //! Effects: Constructs an empty flat_map using the specified + //! comparison object and allocator. + //! + //! Complexity: Constant. + explicit flat_set(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, a) + {} + + //! Effects: Constructs an empty map using the specified comparison object and + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + flat_set(InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, a) + { m_flat_tree.insert_unique(first, last); } + + //! Effects: Constructs an empty flat_set using the specified comparison object and + //! allocator, and inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! Complexity: Linear in N. + template + flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(ordered_range, first, last, comp, a) + {} + + //! Effects: Copy constructs a map. + //! + //! Complexity: Linear in x.size(). + flat_set(const flat_set& x) + : m_flat_tree(x.m_flat_tree) {} + + //! Effects: Move constructs a map. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + flat_set(BOOST_RV_REF(flat_set) mx) + : m_flat_tree(boost::move(mx.m_flat_tree)) + {} + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + flat_set& operator=(BOOST_COPY_ASSIGN_REF(flat_set) x) + { m_flat_tree = x.m_flat_tree; return *this; } + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + flat_set& operator=(BOOST_RV_REF(flat_set) mx) + { m_flat_tree = boost::move(mx.m_flat_tree); return *this; } + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_flat_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return m_flat_tree.key_comp(); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: 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(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return m_flat_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_flat_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return m_flat_tree.cbegin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_flat_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_flat_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return m_flat_tree.cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_flat_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_flat_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const + { return m_flat_tree.crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_flat_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_flat_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return m_flat_tree.crend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_flat_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_flat_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_flat_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(flat_set& x) + { m_flat_tree.swap(x.m_flat_tree); } + + //! Effects: Inserts x if and only if there is no element in the container + //! with key equivalent to the key of x. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + std::pair insert(insert_const_ref_type x) + { return priv_insert(x); } + + #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + std::pair insert(T &x) + { return this->insert(const_cast(x)); } + + template + std::pair insert(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return priv_insert(u); } + #endif + + //! Effects: 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. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + std::pair insert(BOOST_RV_REF(value_type) x) + { return m_flat_tree.insert_unique(boost::move(x)); } + + //! Effects: 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. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's 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(x)); } + + template + iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return priv_insert(position, u); } + #endif + + //! Effects: Inserts an element move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's 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)); } + + //! Requires: first, last are not iterators into *this. + //! + //! Effects: inserts each element from the range [first,last) if and only + //! if there is no element with key equivalent to the key of that element. + //! + //! Complexity: At most N log(size()+N) (N is the distance from first to last) + //! search time plus N*size() insertion time. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + void insert(InputIterator first, InputIterator last) + { m_flat_tree.insert_unique(first, last); } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... if and only if there is no element in the container + //! with key equivalent to the key of x. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + iterator emplace(Args&&... args) + { return m_flat_tree.emplace_unique(boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(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. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + iterator emplace_hint(const_iterator hint, Args&&... args) + { return m_flat_tree.emplace_hint_unique(hint, boost::forward(args)...); } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator emplace() + { return m_flat_tree.emplace_unique(); } + + iterator emplace_hint(const_iterator hint) + { return m_flat_tree.emplace_hint_unique(hint); } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_flat_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); } \ + \ + template \ + iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_flat_tree.emplace_hint_unique(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }\ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Linear to the elements with keys bigger than position + //! + //! Note: Invalidates elements with keys + //! not less than the erased element. + iterator erase(const_iterator position) + { return m_flat_tree.erase(position); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: 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); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: size()*N where N is the distance from first to last. + //! + //! Complexity: 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); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_flat_tree.clear(); } + + //! Effects: Tries to deallocate the excess of memory created + // with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { m_flat_tree.shrink_to_fit(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_flat_tree.find(x); } + + //! Returns: A const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic.s + const_iterator find(const key_type& x) const + { return m_flat_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_flat_tree.find(x) == m_flat_tree.end() ? 0 : 1; } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return m_flat_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_flat_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_flat_tree.upper_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_flat_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return m_flat_tree.equal_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) + { return m_flat_tree.equal_range(x); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return m_flat_tree.capacity(); } + + //! Effects: 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. + //! + //! Throws: If memory allocation allocation throws or T's copy constructor throws. + //! + //! Note: 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 + friend bool operator== (const flat_set&, const flat_set&); + + template + friend bool operator< (const flat_set&, const flat_set&); + + private: + std::pair priv_insert(const T &x) + { return m_flat_tree.insert_unique(x); } + + iterator priv_insert(const_iterator p, const T &x) + { return m_flat_tree.insert_unique(p, x); } + /// @endcond +}; + +template +inline bool operator==(const flat_set& x, + const flat_set& y) + { return x.m_flat_tree == y.m_flat_tree; } + +template +inline bool operator<(const flat_set& x, + const flat_set& y) + { return x.m_flat_tree < y.m_flat_tree; } + +template +inline bool operator!=(const flat_set& x, + const flat_set& y) + { return !(x == y); } + +template +inline bool operator>(const flat_set& x, + const flat_set& y) + { return y < x; } + +template +inline bool operator<=(const flat_set& x, + const flat_set& y) + { return !(y < x); } + +template +inline bool operator>=(const flat_set& x, + const flat_set& y) + { return !(x < y); } + +template +inline void swap(flat_set& x, flat_set& y) + { x.swap(y); } + +/// @cond + +} //namespace container { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value &&has_trivial_destructor::value; +}; +*/ +namespace container { + +// Forward declaration of operators < and ==, needed for friend declaration. + +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template , class A = std::allocator > +#else +template +#endif +class flat_multiset; + +template +inline bool operator==(const flat_multiset& x, + const flat_multiset& y); + +template +inline bool operator<(const flat_multiset& x, + const flat_multiset& y); +/// @endcond + +//! 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 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. +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template , class A = std::allocator > +#else +template +#endif +class flat_multiset +{ + /// @cond + private: + BOOST_COPYABLE_AND_MOVABLE(flat_multiset) + typedef containers_detail::flat_tree, Pred, A> tree_t; + tree_t m_flat_tree; // flat tree representing flat_multiset + typedef typename containers_detail:: + move_const_ref_type::type insert_const_ref_type; + /// @endcond + + 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; + + // allocation/deallocation + explicit flat_multiset(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, a) {} + + template + flat_multiset(InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, a) + { m_flat_tree.insert_equal(first, last); } + + //! Effects: Constructs an empty flat_multiset using the specified comparison object and + //! allocator, and inserts elements from the ordered range [first ,last ). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate. + //! + //! Complexity: Linear in N. + template + flat_multiset(ordered_range_t, InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(ordered_range, first, last, comp, a) + {} + + flat_multiset(const flat_multiset& x) + : m_flat_tree(x.m_flat_tree) {} + + flat_multiset(BOOST_RV_REF(flat_multiset) x) + : m_flat_tree(boost::move(x.m_flat_tree)) + {} + + flat_multiset& operator=(BOOST_COPY_ASSIGN_REF(flat_multiset) x) + { m_flat_tree = x.m_flat_tree; return *this; } + + flat_multiset& operator=(BOOST_RV_REF(flat_multiset) mx) + { m_flat_tree = boost::move(mx.m_flat_tree); return *this; } + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_flat_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return m_flat_tree.key_comp(); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: 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(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return m_flat_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_flat_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return m_flat_tree.cbegin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_flat_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_flat_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return m_flat_tree.cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_flat_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_flat_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const + { return m_flat_tree.crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_flat_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_flat_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return m_flat_tree.crend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_flat_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_flat_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_flat_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(flat_multiset& x) + { m_flat_tree.swap(x.m_flat_tree); } + + //! Effects: Inserts x and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's 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(x)); } + + template + iterator insert(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return priv_insert(u); } + #endif + + //! Effects: Inserts a new value_type move constructed from x + //! and returns the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(BOOST_RV_REF(value_type) x) + { return m_flat_tree.insert_equal(boost::move(x)); } + + //! Effects: Inserts a copy of x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's 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(x)); } + + template + iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return priv_insert(position, u); } + #endif + + //! Effects: Inserts a new value move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's 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)); } + + //! Requires: first, last are not iterators into *this. + //! + //! Effects: inserts each element from the range [first,last) . + //! + //! Complexity: At most N log(size()+N) (N is the distance from first to last) + //! search time plus N*size() insertion time. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + void insert(InputIterator first, InputIterator last) + { m_flat_tree.insert_equal(first, last); } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + iterator emplace(Args&&... args) + { return m_flat_tree.emplace_equal(boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + iterator emplace_hint(const_iterator hint, Args&&... args) + { return m_flat_tree.emplace_hint_equal(hint, boost::forward(args)...); } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator emplace() + { return m_flat_tree.emplace_equal(); } + + iterator emplace_hint(const_iterator hint) + { return m_flat_tree.emplace_hint_equal(hint); } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_flat_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); } \ + \ + template \ + iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_flat_tree.emplace_hint_equal(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Linear to the elements with keys bigger than position + //! + //! Note: Invalidates elements with keys + //! not less than the erased element. + iterator erase(const_iterator position) + { return m_flat_tree.erase(position); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: 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); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: size()*N where N is the distance from first to last. + //! + //! Complexity: 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); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_flat_tree.clear(); } + + //! Effects: Tries to deallocate the excess of memory created + // with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { m_flat_tree.shrink_to_fit(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_flat_tree.find(x); } + + //! Returns: A const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic.s + const_iterator find(const key_type& x) const + { return m_flat_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_flat_tree.count(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return m_flat_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_flat_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_flat_tree.upper_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_flat_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return m_flat_tree.equal_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) + { return m_flat_tree.equal_range(x); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return m_flat_tree.capacity(); } + + //! Effects: 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. + //! + //! Throws: If memory allocation allocation throws or T's copy constructor throws. + //! + //! Note: 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 + friend bool operator== (const flat_multiset&, + const flat_multiset&); + template + friend bool operator< (const flat_multiset&, + const flat_multiset&); + private: + iterator priv_insert(const T &x) + { return m_flat_tree.insert_equal(x); } + + iterator priv_insert(const_iterator p, const T &x) + { return m_flat_tree.insert_equal(p, x); } + /// @endcond +}; + +template +inline bool operator==(const flat_multiset& x, + const flat_multiset& y) + { return x.m_flat_tree == y.m_flat_tree; } + +template +inline bool operator<(const flat_multiset& x, + const flat_multiset& y) + { return x.m_flat_tree < y.m_flat_tree; } + +template +inline bool operator!=(const flat_multiset& x, + const flat_multiset& y) + { return !(x == y); } + +template +inline bool operator>(const flat_multiset& x, + const flat_multiset& y) + { return y < x; } + +template +inline bool operator<=(const flat_multiset& x, + const flat_multiset& y) + { return !(y < x); } + +template +inline bool operator>=(const flat_multiset& x, + const flat_multiset& y) +{ return !(x < y); } + +template +inline void swap(flat_multiset& x, flat_multiset& y) + { x.swap(y); } + +/// @cond + +} //namespace container { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; +}; +*/ +namespace container { + +/// @endcond + +}} + +#include + +#endif /* BOOST_CONTAINERS_FLAT_SET_HPP */ diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp new file mode 100644 index 0000000..ad4aecf --- /dev/null +++ b/include/boost/container/list.hpp @@ -0,0 +1,1373 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_LIST_HPP_ +#define BOOST_CONTAINERS_LIST_HPP_ + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) +#else +//Preprocessor library to emulate perfect forwarding +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +namespace boost { +namespace container { +#else +namespace boost { +namespace container { +#endif + +/// @cond +namespace containers_detail { + +template +struct list_hook +{ + typedef typename containers_detail::bi::make_list_base_hook + , containers_detail::bi::link_mode >::type type; +}; + +template +struct list_node + : public list_hook::type +{ + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + list_node() + : m_data() + {} + + template + list_node(Args &&...args) + : m_data(boost::forward(args)...) + {} + + #else //#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING + + list_node() + : m_data() + {} + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + list_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + : m_data(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \ + {} \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif//#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING + + T m_data; +}; + +template +struct intrusive_list_type +{ + typedef typename A::value_type value_type; + typedef typename boost::pointer_to_other + ::type void_pointer; + typedef typename containers_detail::list_node + node_type; + typedef typename containers_detail::bi::make_list + < node_type + , containers_detail::bi::base_hook::type> + , containers_detail::bi::constant_time_size + , containers_detail::bi::size_type + >::type container_type; + typedef container_type type ; +}; + +} //namespace containers_detail { +/// @endcond + +//! A list is a doubly linked list. That is, it is a Sequence that supports both +//! forward and backward traversal, and (amortized) constant time insertion and +//! removal of elements at the beginning or the end, or in the middle. Lists have +//! the important property that insertion and splicing do not invalidate iterators +//! to list elements, and that even removal invalidates only the iterators that point +//! to the elements that are removed. The ordering of iterators may be changed +//! (that is, list::iterator might have a different predecessor or successor +//! after a list operation than it did before), but the iterators themselves will +//! not be invalidated or made to point to different elements unless that invalidation +//! or mutation is explicit. +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template > +#else +template +#endif +class list + : protected containers_detail::node_alloc_holder + ::type> +{ + /// @cond + typedef typename + containers_detail::intrusive_list_type::type Icont; + typedef list ThisType; + typedef containers_detail::node_alloc_holder AllocHolder; + typedef typename AllocHolder::NodePtr NodePtr; + typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef typename AllocHolder::ValAlloc ValAlloc; + typedef typename AllocHolder::Node Node; + typedef containers_detail::allocator_destroyer Destroyer; + typedef typename AllocHolder::allocator_v1 allocator_v1; + typedef typename AllocHolder::allocator_v2 allocator_v2; + typedef typename AllocHolder::alloc_version alloc_version; + + class equal_to_value + { + typedef typename AllocHolder::value_type value_type; + const value_type &t_; + + public: + equal_to_value(const value_type &t) + : t_(t) + {} + + bool operator()(const value_type &t)const + { return t_ == t; } + }; + + template + struct ValueCompareToNodeCompare + : Pred + { + ValueCompareToNodeCompare(Pred pred) + : Pred(pred) + {} + + bool operator()(const Node &a, const Node &b) const + { return static_cast(*this)(a.m_data, b.m_data); } + + bool operator()(const Node &a) const + { return static_cast(*this)(a.m_data); } + }; + /// @endcond + + public: + //! The type of object, T, stored in the list + typedef T value_type; + //! Pointer to T + typedef typename A::pointer pointer; + //! Const pointer to T + typedef typename A::const_pointer const_pointer; + //! Reference to T + typedef typename A::reference reference; + //! Const reference to T + typedef typename A::const_reference const_reference; + //! An unsigned integral type + typedef typename A::size_type size_type; + //! A signed integral type + typedef typename A::difference_type difference_type; + //! The allocator type + typedef A allocator_type; + //! 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 + { + + 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; + 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; + 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; } + + 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 reverse_iterator; + //! Const iterator used to iterate backwards through a list. + typedef std::reverse_iterator const_reverse_iterator; + + //! Effects: Constructs a list taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + explicit list(const allocator_type &a = A()) + : AllocHolder(a) + {} + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + list(size_type n) + : AllocHolder(A()) + { this->resize(n); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + list(size_type n, const T& value, const A& a = A()) + : AllocHolder(a) + { this->insert(this->cbegin(), n, value); } + + //! Effects: Copy constructs a list. + //! + //! Postcondition: x == *this. + //! + //! Throws: If allocator_type's default constructor or copy constructor throws. + //! + //! Complexity: Linear to the elements x contains. + list(const list& x) + : AllocHolder(x) + { this->insert(this->cbegin(), x.begin(), x.end()); } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + list(BOOST_RV_REF(list) x) + : AllocHolder(boost::move(static_cast(x))) + {} + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts a copy of the range [first, last) in the list. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's constructor taking an dereferenced InIt throws. + //! + //! Complexity: Linear to the range [first, last). + template + list(InpIt first, InpIt last, const A &a = A()) + : AllocHolder(a) + { this->insert(this->cbegin(), first, last); } + + //! Effects: Destroys the list. All stored values are destroyed + //! and used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements. + ~list() + {} //AllocHolder clears the list + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return allocator_type(this->node_alloc()); } + + const stored_allocator_type &get_stored_allocator() const + { return this->node_alloc(); } + + stored_allocator_type &get_stored_allocator() + { return this->node_alloc(); } + + //! Effects: Erases all the elements of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the list. + void clear() + { AllocHolder::clear(alloc_version()); } + + //! Effects: Returns an iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return iterator(this->icont().begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return this->cbegin(); } + + //! Effects: Returns an iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return iterator(this->icont().end()); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return this->cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return this->crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return this->crend(); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return const_iterator(this->non_const_icont().begin()); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return const_iterator(this->non_const_icont().end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const + { return const_reverse_iterator(this->cend()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return const_reverse_iterator(this->cbegin()); } + + //! Effects: Returns true if the list contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return !this->size(); } + + //! Effects: Returns the number of the elements contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return this->icont().size(); } + + //! Effects: Returns the largest possible size of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return AllocHolder::max_size(); } + + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Effects: Inserts a copy of x at the beginning of the list. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_front(const T &x); + + //! Effects: Constructs a new element in the beginning of the list + //! and moves the resources of mx to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: 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) + //! Effects: Inserts a copy of x at the end of the list. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_back(const T &x); + + //! Effects: Constructs a new element in the end of the list + //! and moves the resources of mx to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + void push_back(T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back) + #endif + + //! Effects: Removes the first element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + void pop_front() + { this->erase(this->cbegin()); } + + //! Effects: Removes the last element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + void pop_back() + { const_iterator tmp = this->cend(); this->erase(--tmp); } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference front() + { return *this->begin(); } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference front() const + { return *this->begin(); } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference back() + { return *(--this->end()); } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference back() const + { return *(--this->end()); } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: 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); + } + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default constructed. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: 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); + } + } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() + //! allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(ThisType& x) + { AllocHolder::swap(x); } + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + ThisType& operator=(BOOST_COPY_ASSIGN_REF(ThisType) x) + { + if (this != &x) { + this->assign(x.begin(), x.end()); + } + return *this; + } + + //! Effects: Move assignment. All mx's values are transferred to *this. + //! + //! Postcondition: x.empty(). *this contains a the elements x had + //! before the function. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + ThisType& operator=(BOOST_RV_REF(ThisType) mx) + { + this->clear(); + this->swap(mx); + return *this; + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Inserts n copies of x before p. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void insert(const_iterator p, size_type n, const T& x) + { this->priv_create_and_insert_nodes(p, n, x); } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [first, last) range before p. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws. + //! + //! Complexity: Linear to std::distance [first, last). + template + void insert(const_iterator p, InpIt first, InpIt last) + { + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_insert_dispatch(p, first, last, Result()); + } + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Insert a copy of x before position. + //! + //! Throws: If memory allocation throws or x's copy constructor throws. + //! + //! Complexity: Amortized constant time. + iterator insert(const_iterator position, const T &x); + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Insert a new element before position with mx's resources. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: 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 + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the end of the list. + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Constant + template + void emplace_back(Args&&... args) + { + this->emplace(this->cend(), boost::forward(args)...); + } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the beginning of the list. + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Constant + template + void emplace_front(Args&&... args) + { + this->emplace(this->cbegin(), boost::forward(args)...); + } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... before p. + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Constant + template + iterator emplace(const_iterator p, Args&&... args) + { + typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator()); + new ((void*)containers_detail::get_pointer(d.get())) Node(boost::forward(args)...); + NodePtr node = d.get(); + d.release(); + return iterator(this->icont().insert(p.get(), *node)); + } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //0 args + void emplace_back() + { this->emplace(this->cend()); } + + void emplace_front() + { this->emplace(this->cbegin()); } + + iterator emplace(const_iterator p) + { + typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator()); + new ((void*)containers_detail::get_pointer(d.get())) Node(); + NodePtr node = d.get(); + d.release(); + return iterator(this->icont().insert(p.get(), *node)); + } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + this->emplace(this->cend(), BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + } \ + \ + template \ + void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { this->emplace(this->cbegin(), BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));} \ + \ + template \ + iterator emplace(const_iterator p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator()); \ + new ((void*)containers_detail::get_pointer(d.get())) \ + Node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + NodePtr node = d.get(); \ + d.release(); \ + return iterator(this->icont().insert(p.get(), *node)); \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Erases the element at p p. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + iterator erase(const_iterator p) + { return iterator(this->icont().erase_and_dispose(p.get(), Destroyer(this->node_alloc()))); } + + //! Requires: first and last must be valid iterator to elements in *this. + //! + //! Effects: Erases the elements pointed by [first, last). + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the distance between first and last. + iterator erase(const_iterator first, const_iterator last) + { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); } + + //! Effects: Assigns the n copies of val to *this. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void assign(size_type n, const T& val) + { this->priv_fill_assign(n, val); } + + //! Effects: Assigns the the range [first, last) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! Complexity: Linear to n. + template + void assign(InpIt first, InpIt last) + { + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_assign_dispatch(first, last, Result()); + } + + //! Requires: p must point to an element contained + //! by the list. x != *this + //! + //! Effects: Transfers all the elements of list x to this list, before the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Constant. + //! + //! Note: 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) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice(p.get(), x.icont()); + } + else{ + throw std::runtime_error("list::splice called with unequal allocators"); + } + } + + //! Requires: p must point to an element contained + //! by this list. i must point to an element contained in list x. + //! + //! Effects: 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. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Constant. + //! + //! Note: 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) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice(p.get(), x.icont(), i.get()); + } + else{ + throw std::runtime_error("list::splice called with unequal allocators"); + } + } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! + //! Effects: 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. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear to the number of elements transferred. + //! + //! Note: 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) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice(p.get(), x.icont(), first.get(), last.get()); + } + else{ + throw std::runtime_error("list::splice called with unequal allocators"); + } + } + + //! Requires: 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) + //! + //! Effects: 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. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Constant. + //! + //! Note: 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) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n); + } + else{ + throw std::runtime_error("list::splice called with unequal allocators"); + } + } + + //! Effects: Reverses the order of elements in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time. + //! + //! Note: Iterators and references are not invalidated + void reverse() + { this->icont().reverse(); } + + //! Effects: Removes all the elements that compare equal to value. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: 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)); } + + //! Effects: Removes all the elements for which a specified + //! predicate is satisfied. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time. It performs exactly size() calls to the predicate. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_if(Pred pred) + { + typedef ValueCompareToNodeCompare Predicate; + this->icont().remove_and_dispose_if(Predicate(pred), Destroyer(this->node_alloc())); + } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that are equal from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear time (size()-1 comparisons calls to pred()). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void unique() + { this->unique(value_equal()); } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time (size()-1 comparisons equality comparisons). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique(BinaryPredicate binary_pred) + { + typedef ValueCompareToNodeCompare Predicate; + this->icont().unique_and_dispose(Predicate(binary_pred), Destroyer(this->node_alloc())); + } + + //! Requires: The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this according to std::less. 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. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + void merge(list& x) + { this->merge(x, value_less()); } + + //! Requires: 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. + //! + //! Effects: 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. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references to *this are not invalidated. + template + void merge(list &x, StrictWeakOrdering comp) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().merge(x.icont(), + ValueCompareToNodeCompare(comp)); + } + else{ + throw std::runtime_error("list::merge called with unequal allocators"); + } + } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: Nothing. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + void sort() + { this->sort(value_less()); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: Nothing. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + template + void sort(StrictWeakOrdering comp) + { + // nothing if the list has length 0 or 1. + if (this->size() < 2) + return; + this->icont().sort(ValueCompareToNodeCompare(comp)); + } + + /// @cond + private: + + iterator priv_insert(const_iterator p, const T &x) + { + NodePtr tmp = AllocHolder::create_node(x); + return iterator(this->icont().insert(p.get(), *tmp)); + } + + iterator priv_insert(const_iterator p, BOOST_RV_REF(T) x) + { + NodePtr tmp = AllocHolder::create_node(boost::move(x)); + return iterator(this->icont().insert(p.get(), *tmp)); + } + + void priv_push_back (const T &x) + { this->insert(this->cend(), x); } + + void priv_push_back (BOOST_RV_REF(T) x) + { this->insert(this->cend(), boost::move(x)); } + + void priv_push_front (const T &x) + { this->insert(this->cbegin(), x); } + + void priv_push_front (BOOST_RV_REF(T) x) + { this->insert(this->cbegin(), boost::move(x)); } + + //Iterator range version + template + void priv_create_and_insert_nodes + (const_iterator pos, InpIterator beg, InpIterator end) + { + typedef typename std::iterator_traits::iterator_category ItCat; + priv_create_and_insert_nodes(pos, beg, end, alloc_version(), ItCat()); + } + + template + 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 + 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_; + + public: + insertion_functor(Icont &icont, typename Icont::const_iterator pos) + : icont_(icont), pos_(pos) + {} + + void operator()(Node &n) + { this->icont_.insert(pos_, n); } + }; + + + template + 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())); + } + } + + //Default constructed version + void priv_create_and_insert_nodes(const_iterator pos, size_type n) + { + typedef default_construct_iterator 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 cvalue_iterator; + this->priv_create_and_insert_nodes(pos, cvalue_iterator(x, n), cvalue_iterator()); + } + + //Dispatch to detect iterator range or integer overloads + template + void priv_insert_dispatch(const_iterator p, + InputIter first, InputIter last, + containers_detail::false_) + { this->priv_create_and_insert_nodes(p, first, last); } + + template + void priv_insert_dispatch(const_iterator p, Integer n, Integer x, containers_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 + void priv_assign_dispatch(Integer n, Integer val, containers_detail::true_) + { this->priv_fill_assign((size_type) n, (T) val); } + + template + void priv_assign_dispatch(InputIter first2, InputIter last2, containers_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 + { + bool operator()(const value_type &a, const value_type &b) const + { return a < b; } + }; + + struct value_equal + { + bool operator()(const value_type &a, const value_type &b) const + { return a == b; } + }; + /// @endcond + +}; + +template +inline 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; +} + +template +inline bool operator<(const list& x, + const list& y) +{ + return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); +} + +template +inline bool operator!=(const list& x, const list& y) +{ + return !(x == y); +} + +template +inline bool operator>(const list& x, const list& y) +{ + return y < x; +} + +template +inline bool operator<=(const list& x, const list& y) +{ + return !(y < x); +} + +template +inline bool operator>=(const list& x, const list& y) +{ + return !(x < y); +} + +template +inline void swap(list& x, list& y) +{ + x.swap(y); +} + +/// @cond + +} //namespace container { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value; +}; +*/ +namespace container { + +/// @endcond + +}} + +#include + +#endif // BOOST_CONTAINERS_LIST_HPP_ diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp new file mode 100644 index 0000000..9eac512 --- /dev/null +++ b/include/boost/container/map.hpp @@ -0,0 +1,1292 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_MAP_HPP +#define BOOST_CONTAINERS_MAP_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +inline bool operator==(const map& x, + const map& y); + +template +inline bool operator<(const map& x, + const map& y); +/// @endcond + +//! 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 the key_type is Key and the value_type is std::pair. +//! +//! Pred is the ordering function for Keys (e.g. std::less). +//! +//! A is the allocator to allocate the value_types +//! (e.g. allocator< std::pair > ). +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template >, class A = std::allocator > +#else +template +#endif +class map +{ + /// @cond + private: + BOOST_COPYABLE_AND_MOVABLE(map) + typedef containers_detail::rbtree, + containers_detail::select1st< std::pair >, + Pred, + A> tree_t; + tree_t m_tree; // red-black tree representing map + + /// @endcond + + 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 nonconst_value_type; + typedef containers_detail::pair + nonconst_impl_value_type; + + /// @cond + class value_compare_impl + : public Pred, + public std::binary_function + { + friend class map; + 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; + + //! Effects: Constructs an empty map using the specified comparison object + //! and allocator. + //! + //! Complexity: Constant. + explicit map(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(comp, a) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((containers_detail::is_same, typename A::value_type>::value)); + } + + //! Effects: Constructs an empty map using the specified comparison object and + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + map(InputIterator first, InputIterator last, const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(first, last, comp, a, true) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((containers_detail::is_same, typename A::value_type>::value)); + } + + //! Effects: Constructs an empty map using the specified comparison object and + //! allocator, and inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! Complexity: Linear in N. + template + 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) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((containers_detail::is_same, typename A::value_type>::value)); + } + + //! Effects: Copy constructs a map. + //! + //! Complexity: Linear in x.size(). + map(const map& x) + : m_tree(x.m_tree) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((containers_detail::is_same, typename A::value_type>::value)); + } + + //! Effects: Move constructs a map. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + map(BOOST_RV_REF(map) x) + : m_tree(boost::move(x.m_tree)) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((containers_detail::is_same, typename A::value_type>::value)); + } + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + map& operator=(BOOST_COPY_ASSIGN_REF(map) x) + { m_tree = x.m_tree; return *this; } + + //! Effects: this->swap(x.get()). + //! + //! Complexity: Constant. + map& operator=(BOOST_RV_REF(map) x) + { m_tree = boost::move(x.m_tree); return *this; } + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return value_compare(m_tree.key_comp()); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: 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(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return m_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_tree.begin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_tree.end(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_tree.rbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_tree.rend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_tree.max_size(); } + + //! 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. + //! + //! Complexity: Logarithmic. + T& operator[](const key_type& k) + { + //we can optimize this + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)){ + containers_detail::value_init v; + value_type val(k, boost::move(v.m_t)); + i = insert(i, boost::move(val)); + } + return (*i).second; + } + + //! 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. + //! + //! Complexity: Logarithmic. + T& operator[](BOOST_RV_REF(key_type) mk) + { + key_type &k = mk; + //we can optimize this + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)){ + value_type val(boost::move(k), boost::move(T())); + i = insert(i, boost::move(val)); + } + return (*i).second; + } + + //! Returns: A reference to the element whose key is equivalent to x. + //! Throws: An exception object of type out_of_range if no such element is present. + //! Complexity: logarithmic. + T& at(const key_type& k) + { + iterator i = this->find(k); + if(i == this->end()){ + throw std::out_of_range("key not found"); + } + return i->second; + } + + //! Returns: A reference to the element whose key is equivalent to x. + //! Throws: An exception object of type out_of_range if no such element is present. + //! Complexity: logarithmic. + const T& at(const key_type& k) const + { + const_iterator i = this->find(k); + if(i == this->end()){ + throw std::out_of_range("key not found"); + } + return i->second; + } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(map& x) + { m_tree.swap(x.m_tree); } + + //! Effects: Inserts x if and only if there is no element in the container + //! with key equivalent to the key of x. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic. + std::pair insert(const value_type& x) + { return m_tree.insert_unique(x); } + + //! Effects: 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. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic. + std::pair insert(const nonconst_value_type& x) + { return m_tree.insert_unique(x); } + + //! Effects: 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. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic. + std::pair insert(BOOST_RV_REF(nonconst_value_type) x) + { return m_tree.insert_unique(boost::move(x)); } + + //! Effects: 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. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic. + std::pair insert(BOOST_RV_REF(nonconst_impl_value_type) x) + { return m_tree.insert_unique(boost::move(x)); } + + //! Effects: 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. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic. + std::pair insert(BOOST_RV_REF(value_type) x) + { return m_tree.insert_unique(boost::move(x)); } + + //! Effects: 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. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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); } + + //! Effects: Move constructs a new value from x if and only if there is + //! no element in the container with key equivalent to the key of x. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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)); } + + //! Effects: Move constructs a new value from x if and only if there is + //! no element in the container with key equivalent to the key of x. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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)); } + + //! Effects: Inserts a copy of x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + iterator insert(iterator position, const nonconst_value_type& x) + { return m_tree.insert_unique(position, x); } + + //! Effects: Inserts an element move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + iterator insert(iterator position, BOOST_RV_REF(value_type) x) + { return m_tree.insert_unique(position, boost::move(x)); } + + //! Requires: first, last are not iterators into *this. + //! + //! Effects: inserts each element from the range [first,last) if and only + //! if there is no element with key equivalent to the key of that element. + //! + //! Complexity: At most N log(size()+N) (N is the distance from first to last) + template + void insert(InputIterator first, InputIterator last) + { m_tree.insert_unique(first, last); } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the container if and only if there is + //! no element in the container with an equivalent key. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + template + iterator emplace(Args&&... args) + { return m_tree.emplace_unique(boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the container if and only if there is + //! no element in the container with an equivalent key. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + template + iterator emplace_hint(const_iterator hint, Args&&... args) + { return m_tree.emplace_hint_unique(hint, boost::forward(args)...); } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator emplace() + { return m_tree.emplace_unique(); } + + iterator emplace_hint(const_iterator hint) + { return m_tree.emplace_hint_unique(hint); } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); } \ + \ + template \ + iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_tree.emplace_hint_unique(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));}\ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Amortized constant time + iterator erase(const_iterator position) + { return m_tree.erase(position); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: log(size()) + count(k) + size_type erase(const key_type& x) + { return m_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: 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); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_tree.clear(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_tree.find(x); } + + //! Returns: A const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + const_iterator find(const key_type& x) const + { return m_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_tree.find(x) == m_tree.end() ? 0 : 1; } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return m_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_tree.upper_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) + { return m_tree.equal_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) const + { return m_tree.equal_range(x); } + + /// @cond + template + friend bool operator== (const map&, + const map&); + template + friend bool operator< (const map&, + const map&); + /// @endcond +}; + +template +inline bool operator==(const map& x, + const map& y) + { return x.m_tree == y.m_tree; } + +template +inline bool operator<(const map& x, + const map& y) + { return x.m_tree < y.m_tree; } + +template +inline bool operator!=(const map& x, + const map& y) + { return !(x == y); } + +template +inline bool operator>(const map& x, + const map& y) + { return y < x; } + +template +inline bool operator<=(const map& x, + const map& y) + { return !(y < x); } + +template +inline bool operator>=(const map& x, + const map& y) + { return !(x < y); } + +template +inline void swap(map& x, map& y) + { x.swap(y); } + +/// @cond + +// Forward declaration of operators < and ==, needed for friend declaration. + +template +inline bool operator==(const multimap& x, + const multimap& y); + +template +inline bool operator<(const multimap& x, + const multimap& y); + +} //namespace container { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; +}; +*/ +namespace container { + +/// @endcond + +//! A multimap is a kind of associative container that supports equivalent keys +//! (possibly containing multiple copies of the same key value) and provides for +//! fast retrieval of values of another type T based on the keys. The multimap class +//! supports bidirectional iterators. +//! +//! A multimap satisfies all of the requirements of a container and of a reversible +//! container and of an associative container. For a +//! map the key_type is Key and the value_type is std::pair. +//! +//! Pred is the ordering function for Keys (e.g. std::less). +//! +//! A is the allocator to allocate the value_types +//!(e.g. allocator< std::pair<const Key, T> >). +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template >, class A = std::allocator > +#else +template +#endif +class multimap +{ + /// @cond + private: + BOOST_COPYABLE_AND_MOVABLE(multimap) + typedef containers_detail::rbtree, + containers_detail::select1st< std::pair >, + Pred, + A> tree_t; + tree_t m_tree; // red-black tree representing map + /// @endcond + + 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 nonconst_value_type; + typedef containers_detail::pair + nonconst_impl_value_type; + + /// @cond + class value_compare_impl + : public Pred, + public std::binary_function + { + friend class multimap; + 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; + + //! Effects: Constructs an empty multimap using the specified comparison + //! object and allocator. + //! + //! Complexity: Constant. + explicit multimap(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(comp, a) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((containers_detail::is_same, typename A::value_type>::value)); + } + + //! Effects: Constructs an empty multimap using the specified comparison object + //! and allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + multimap(InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(first, last, comp, a, false) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((containers_detail::is_same, typename A::value_type>::value)); + } + + //! Effects: Constructs an empty multimap using the specified comparison object and + //! allocator, and inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate. + //! + //! Complexity: Linear in N. + template + multimap(ordered_range_t ordered_range, InputIterator first, InputIterator last, const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(ordered_range, first, last, comp, a) + {} + + + //! Effects: Copy constructs a multimap. + //! + //! Complexity: Linear in x.size(). + multimap(const multimap& x) + : m_tree(x.m_tree) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((containers_detail::is_same, typename A::value_type>::value)); + } + + //! Effects: Move constructs a multimap. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + multimap(BOOST_RV_REF(multimap) x) + : m_tree(boost::move(x.m_tree)) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((containers_detail::is_same, typename A::value_type>::value)); + } + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + multimap& operator=(BOOST_COPY_ASSIGN_REF(multimap) x) + { m_tree = x.m_tree; return *this; } + + //! Effects: this->swap(x.get()). + //! + //! Complexity: Constant. + multimap& operator=(BOOST_RV_REF(multimap) x) + { m_tree = boost::move(x.m_tree); return *this; } + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return value_compare(m_tree.key_comp()); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: 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(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return m_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_tree.begin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_tree.end(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_tree.rbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_tree.rend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(multimap& x) + { m_tree.swap(x.m_tree); } + + //! Effects: Inserts x and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: Logarithmic. + iterator insert(const value_type& x) + { return m_tree.insert_equal(x); } + + //! Effects: Inserts a new value constructed from x and returns + //! the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic. + iterator insert(const nonconst_value_type& x) + { return m_tree.insert_equal(x); } + + //! Effects: Inserts a new value move-constructed from x and returns + //! the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic. + iterator insert(BOOST_RV_REF(nonconst_value_type) x) + { return m_tree.insert_equal(boost::move(x)); } + + //! Effects: Inserts a new value move-constructed from x and returns + //! the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic. + iterator insert(BOOST_RV_REF(nonconst_impl_value_type) x) + { return m_tree.insert_equal(boost::move(x)); } + + //! Effects: Inserts a copy of x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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); } + + //! Effects: Inserts a new value constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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); } + + //! Effects: Inserts a new value move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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)); } + + //! Effects: Inserts a new value move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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)); } + + //! Requires: first, last are not iterators into *this. + //! + //! Effects: inserts each element from the range [first,last) . + //! + //! Complexity: At most N log(size()+N) (N is the distance from first to last) + template + void insert(InputIterator first, InputIterator last) + { m_tree.insert_equal(first, last); } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + template + iterator emplace(Args&&... args) + { return m_tree.emplace_equal(boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + template + iterator emplace_hint(const_iterator hint, Args&&... args) + { return m_tree.emplace_hint_equal(hint, boost::forward(args)...); } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator emplace() + { return m_tree.emplace_equal(); } + + iterator emplace_hint(const_iterator hint) + { return m_tree.emplace_hint_equal(hint); } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); } \ + \ + template \ + iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_tree.emplace_hint_equal(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }\ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Amortized constant time + iterator erase(const_iterator position) + { return m_tree.erase(position); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: log(size()) + count(k) + size_type erase(const key_type& x) + { return m_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: 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); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_tree.clear(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_tree.find(x); } + + //! Returns: A const iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + const_iterator find(const key_type& x) const + { return m_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_tree.count(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + {return m_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) + { return m_tree.equal_range(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return m_tree.equal_range(x); } + + /// @cond + template + friend bool operator== (const multimap& x, + const multimap& y); + + template + friend bool operator< (const multimap& x, + const multimap& y); + /// @endcond +}; + +template +inline bool operator==(const multimap& x, + const multimap& y) +{ return x.m_tree == y.m_tree; } + +template +inline bool operator<(const multimap& x, + const multimap& y) +{ return x.m_tree < y.m_tree; } + +template +inline bool operator!=(const multimap& x, + const multimap& y) +{ return !(x == y); } + +template +inline bool operator>(const multimap& x, + const multimap& y) +{ return y < x; } + +template +inline bool operator<=(const multimap& x, + const multimap& y) +{ return !(y < x); } + +template +inline bool operator>=(const multimap& x, + const multimap& y) +{ return !(x < y); } + +template +inline void swap(multimap& x, multimap& y) +{ x.swap(y); } + +/// @cond + +} //namespace container { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; +}; +*/ +namespace container { + +/// @endcond + +}} + +#include + +#endif /* BOOST_CONTAINERS_MAP_HPP */ + diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp new file mode 100644 index 0000000..8ea4e76 --- /dev/null +++ b/include/boost/container/set.hpp @@ -0,0 +1,1163 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_SET_HPP +#define BOOST_CONTAINERS_SET_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING +#include +#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 +inline bool operator==(const set& x, + const set& y); + +template +inline bool operator<(const set& x, + const set& y); +/// @endcond + +//! A set is a kind of associative container that supports unique keys (contains at +//! most one of each key value) and provides for fast retrieval of the keys themselves. +//! Class set supports bidirectional iterators. +//! +//! A set satisfies all of the requirements of a container and of a reversible container +//! , and of an associative container. A set also provides most operations described in +//! for unique keys. +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template , class A = std::allocator > +#else +template +#endif +class set +{ + /// @cond + private: + BOOST_COPYABLE_AND_MOVABLE(set) + typedef containers_detail::rbtree, Pred, A> tree_t; + tree_t m_tree; // red-black tree representing set + typedef typename containers_detail:: + move_const_ref_type::type insert_const_ref_type; + /// @endcond + + 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; + + //! Effects: Constructs an empty set using the specified comparison object + //! and allocator. + //! + //! Complexity: Constant. + explicit set(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(comp, a) + {} + + //! Effects: Constructs an empty set using the specified comparison object and + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + set(InputIterator first, InputIterator last, const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(first, last, comp, a, true) + {} + + //! Effects: Constructs an empty set using the specified comparison object and + //! allocator, and inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! Complexity: Linear in N. + template + 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) + {} + + //! Effects: Copy constructs a set. + //! + //! Complexity: Linear in x.size(). + set(const set& x) + : m_tree(x.m_tree) + {} + + //! Effects: Move constructs a set. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + set(BOOST_RV_REF(set) x) + : m_tree(boost::move(x.m_tree)) + {} + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + set& operator=(BOOST_COPY_ASSIGN_REF(set) x) + { m_tree = x.m_tree; return *this; } + + //! Effects: this->swap(x.get()). + //! + //! Complexity: Constant. + set& operator=(BOOST_RV_REF(set) x) + { m_tree = boost::move(x.m_tree); return *this; } + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: 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(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant + iterator begin() + { return m_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_tree.begin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_tree.end(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_tree.rbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_tree.rend(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return m_tree.cbegin(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return m_tree.cend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const + { return m_tree.crbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return m_tree.crend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(set& x) + { m_tree.swap(x.m_tree); } + + //! Effects: Inserts x if and only if there is no element in the container + //! with key equivalent to the key of x. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic. + std::pair insert(insert_const_ref_type x) + { return priv_insert(x); } + + #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + std::pair insert(T &x) + { return this->insert(const_cast(x)); } + + template + std::pair insert(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return priv_insert(u); } + #endif + + //! Effects: 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. + //! + //! Returns: 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. + //! + //! Complexity: Logarithmic. + std::pair insert(BOOST_RV_REF(value_type) x) + { return m_tree.insert_unique(boost::move(x)); } + + //! Effects: 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. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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(x)); } + + template + iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return priv_insert(position, u); } + #endif + + //! Effects: Inserts an element move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + iterator insert(const_iterator p, BOOST_RV_REF(value_type) x) + { return m_tree.insert_unique(p, boost::move(x)); } + + //! Requires: first, last are not iterators into *this. + //! + //! Effects: inserts each element from the range [first,last) if and only + //! if there is no element with key equivalent to the key of that element. + //! + //! Complexity: At most N log(size()+N) (N is the distance from first to last) + template + void insert(InputIterator first, InputIterator last) + { m_tree.insert_unique(first, last); } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(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. + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Logarithmic. + template + iterator emplace(Args&&... args) + { return m_tree.emplace_unique(boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(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. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + template + iterator emplace_hint(const_iterator hint, Args&&... args) + { return m_tree.emplace_hint_unique(hint, boost::forward(args)...); } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator emplace() + { return m_tree.emplace_unique(); } + + iterator emplace_hint(const_iterator hint) + { return m_tree.emplace_hint_unique(hint); } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); } \ + \ + template \ + iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_tree.emplace_hint_unique(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));}\ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Erases the element pointed to by p. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Amortized constant time + iterator erase(const_iterator p) + { return m_tree.erase(p); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: log(size()) + count(k) + size_type erase(const key_type& x) + { return m_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: 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); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_tree.clear(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_tree.find(x); } + + //! Returns: A const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + const_iterator find(const key_type& x) const + { return m_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_tree.find(x) == m_tree.end() ? 0 : 1; } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return m_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_tree.upper_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) + { return m_tree.equal_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return m_tree.equal_range(x); } + + /// @cond + template + friend bool operator== (const set&, const set&); + + template + friend bool operator< (const set&, const set&); + + private: + std::pair priv_insert(const T &x) + { return m_tree.insert_unique(x); } + + iterator priv_insert(const_iterator p, const T &x) + { return m_tree.insert_unique(p, x); } + + /// @endcond +}; + +template +inline bool operator==(const set& x, + const set& y) +{ return x.m_tree == y.m_tree; } + +template +inline bool operator<(const set& x, + const set& y) +{ return x.m_tree < y.m_tree; } + +template +inline bool operator!=(const set& x, + const set& y) +{ return !(x == y); } + +template +inline bool operator>(const set& x, + const set& y) +{ return y < x; } + +template +inline bool operator<=(const set& x, + const set& y) +{ return !(y < x); } + +template +inline bool operator>=(const set& x, + const set& y) +{ return !(x < y); } + +template +inline void swap(set& x, set& y) +{ x.swap(y); } + +/// @cond + +} //namespace container { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; +}; +*/ +namespace container { + +// Forward declaration of operators < and ==, needed for friend declaration. + +template +inline bool operator==(const multiset& x, + const multiset& y); + +template +inline bool operator<(const multiset& x, + const multiset& y); +/// @endcond + +//! A multiset is a kind of associative container that supports equivalent keys +//! (possibly contains multiple copies of the same key value) and provides for +//! fast retrieval of the keys themselves. Class multiset supports bidirectional iterators. +//! +//! A multiset satisfies all of the requirements of a container and of a reversible +//! container, and of an associative container). multiset also provides most operations +//! described for duplicate keys. +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template , class A = std::allocator > +#else +template +#endif +class multiset +{ + /// @cond + private: + BOOST_COPYABLE_AND_MOVABLE(multiset) + typedef containers_detail::rbtree, Pred, A> tree_t; + tree_t m_tree; // red-black tree representing multiset + typedef typename containers_detail:: + move_const_ref_type::type insert_const_ref_type; + /// @endcond + + 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; + + //! Effects: Constructs an empty multiset using the specified comparison + //! object and allocator. + //! + //! Complexity: Constant. + explicit multiset(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(comp, a) + {} + + //! Effects: Constructs an empty multiset using the specified comparison object + //! and allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + multiset(InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(first, last, comp, a, false) + {} + + //! Effects: Constructs an empty multiset using the specified comparison object and + //! allocator, and inserts elements from the ordered range [first ,last ). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! Requires: [first ,last) must be ordered according to the predicate. + //! + //! Complexity: Linear in N. + template + multiset( ordered_range_t ordered_range, InputIterator first, InputIterator last + , const Pred& comp = Pred() + , const allocator_type& a = allocator_type()) + : m_tree(ordered_range, first, last, comp, a) + {} + + //! Effects: Copy constructs a multiset. + //! + //! Complexity: Linear in x.size(). + multiset(const multiset& x) + : m_tree(x.m_tree) + {} + + //! Effects: Move constructs a multiset. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + multiset(BOOST_RV_REF(multiset) x) + : m_tree(boost::move(x.m_tree)) + {} + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + multiset& operator=(BOOST_COPY_ASSIGN_REF(multiset) x) + { m_tree = x.m_tree; return *this; } + + //! Effects: this->swap(x.get()). + //! + //! Complexity: Constant. + multiset& operator=(BOOST_RV_REF(multiset) x) + { m_tree = boost::move(x.m_tree); return *this; } + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: 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(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return m_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_tree.begin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_tree.end(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_tree.rbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_tree.rend(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return m_tree.cbegin(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return m_tree.cend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const + { return m_tree.crbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return m_tree.crend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(multiset& x) + { m_tree.swap(x.m_tree); } + + //! Effects: Inserts x and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: 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(x)); } + + template + iterator insert(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return priv_insert(u); } + #endif + + //! Effects: Inserts a copy of x in the container. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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)); } + + //! Effects: Inserts a copy of x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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(x)); } + + template + iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return priv_insert(position, u); } + #endif + + //! Effects: Inserts a value move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: 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)); } + + //! Requires: first, last are not iterators into *this. + //! + //! Effects: inserts each element from the range [first,last) . + //! + //! Complexity: At most N log(size()+N) (N is the distance from first to last) + template + void insert(InputIterator first, InputIterator last) + { m_tree.insert_equal(first, last); } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: Logarithmic. + template + iterator emplace(Args&&... args) + { return m_tree.emplace_equal(boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + template + iterator emplace_hint(const_iterator hint, Args&&... args) + { return m_tree.emplace_hint_equal(hint, boost::forward(args)...); } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + iterator emplace() + { return m_tree.emplace_equal(); } + + iterator emplace_hint(const_iterator hint) + { return m_tree.emplace_hint_equal(hint); } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); } \ + \ + template \ + iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { return m_tree.emplace_hint_equal(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }\ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Erases the element pointed to by p. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Amortized constant time + iterator erase(const_iterator p) + { return m_tree.erase(p); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: log(size()) + count(k) + size_type erase(const key_type& x) + { return m_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: 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); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_tree.clear(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_tree.find(x); } + + //! Returns: A const iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + const_iterator find(const key_type& x) const + { return m_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_tree.count(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return m_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_tree.upper_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) + { return m_tree.equal_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return m_tree.equal_range(x); } + + /// @cond + template + friend bool operator== (const multiset&, + const multiset&); + template + friend bool operator< (const multiset&, + const multiset&); + private: + iterator priv_insert(const T &x) + { return m_tree.insert_equal(x); } + + iterator priv_insert(const_iterator p, const T &x) + { return m_tree.insert_equal(p, x); } + + /// @endcond +}; + +template +inline bool operator==(const multiset& x, + const multiset& y) +{ return x.m_tree == y.m_tree; } + +template +inline bool operator<(const multiset& x, + const multiset& y) +{ return x.m_tree < y.m_tree; } + +template +inline bool operator!=(const multiset& x, + const multiset& y) +{ return !(x == y); } + +template +inline bool operator>(const multiset& x, + const multiset& y) +{ return y < x; } + +template +inline bool operator<=(const multiset& x, + const multiset& y) +{ return !(y < x); } + +template +inline bool operator>=(const multiset& x, + const multiset& y) +{ return !(x < y); } + +template +inline void swap(multiset& x, multiset& y) +{ x.swap(y); } + +/// @cond + +} //namespace container { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value && has_trivial_destructor::value; +}; +*/ +namespace container { + +/// @endcond + +}} + +#include + +#endif /* BOOST_CONTAINERS_SET_HPP */ + diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp new file mode 100644 index 0000000..d5121a0 --- /dev/null +++ b/include/boost/container/slist.hpp @@ -0,0 +1,1536 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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_CONTAINERS_SLIST_HPP +#define BOOST_CONTAINERS_SLIST_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) +//Preprocessor library to emulate perfect forwarding +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +namespace boost { +namespace container { +#else +namespace boost { +namespace container { +#endif + +/// @cond + +namespace containers_detail { + +template +struct slist_hook +{ + typedef typename containers_detail::bi::make_slist_base_hook + , containers_detail::bi::link_mode >::type type; +}; + +template +struct slist_node + : public slist_hook::type +{ + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + slist_node() + : m_data() + {} + + template + slist_node(Args &&...args) + : m_data(boost::forward(args)...) + {} + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + slist_node() + : m_data() + {} + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + slist_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + : m_data(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \ + {} \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif//#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + T m_data; +}; + +template +struct intrusive_slist_type +{ + typedef typename A::value_type value_type; + typedef typename boost::pointer_to_other + ::type void_pointer; + typedef typename containers_detail::slist_node + node_type; + + typedef typename containers_detail::bi::make_slist + ::type> + ,containers_detail::bi::constant_time_size + ,containers_detail::bi::size_type + >::type container_type; + typedef container_type type ; +}; + +} //namespace containers_detail { + +/// @endcond + +//! An slist is a singly linked list: a list where each element is linked to the next +//! element, but not to the previous element. That is, it is a Sequence that +//! supports forward but not backward traversal, and (amortized) constant time +//! insertion and removal of elements. Slists, like lists, have the important +//! property that insertion and splicing do not invalidate iterators to list elements, +//! and that even removal invalidates only the iterators that point to the elements +//! that are removed. The ordering of iterators may be changed (that is, +//! slist::iterator might have a different predecessor or successor after a list +//! operation than it did before), but the iterators themselves will not be invalidated +//! or made to point to different elements unless that invalidation or mutation is explicit. +//! +//! The main difference between slist and list is that list's iterators are bidirectional +//! iterators, while slist's iterators are forward iterators. This means that slist is +//! less versatile than list; frequently, however, bidirectional iterators are +//! unnecessary. You should usually use slist unless you actually need the extra +//! functionality of list, because singly linked lists are smaller and faster than double +//! linked lists. +//! +//! Important performance note: like every other Sequence, slist defines the member +//! functions insert and erase. Using these member functions carelessly, however, can +//! result in disastrously slow programs. The problem is that insert's first argument is +//! an iterator p, and that it inserts the new element(s) before p. This means that +//! insert must find the iterator just before p; this is a constant-time operation +//! for list, since list has bidirectional iterators, but for slist it must find that +//! iterator by traversing the list from the beginning up to p. In other words: +//! insert and erase are slow operations anywhere but near the beginning of the slist. +//! +//! Slist provides the member functions insert_after and erase_after, which are constant +//! time operations: you should always use insert_after and erase_after whenever +//! possible. If you find that insert_after and erase_after aren't adequate for your +//! needs, and that you often need to use insert and erase in the middle of the list, +//! then you should probably use list instead of slist. +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template > +#else +template +#endif +class slist + : protected containers_detail::node_alloc_holder + ::type> +{ + /// @cond + typedef typename containers_detail:: + move_const_ref_type::type insert_const_ref_type; + typedef typename + containers_detail::intrusive_slist_type::type Icont; + typedef containers_detail::node_alloc_holder AllocHolder; + typedef typename AllocHolder::NodePtr NodePtr; + typedef slist ThisType; + typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef typename AllocHolder::ValAlloc ValAlloc; + typedef typename AllocHolder::Node Node; + typedef containers_detail::allocator_destroyer Destroyer; + typedef typename AllocHolder::allocator_v1 allocator_v1; + typedef typename AllocHolder::allocator_v2 allocator_v2; + typedef typename AllocHolder::alloc_version alloc_version; + + class equal_to_value + { + typedef typename AllocHolder::value_type value_type; + const value_type &t_; + + public: + equal_to_value(const value_type &t) + : t_(t) + {} + + bool operator()(const value_type &t)const + { return t_ == t; } + }; + + template + struct ValueCompareToNodeCompare + : Pred + { + ValueCompareToNodeCompare(Pred pred) + : Pred(pred) + {} + + bool operator()(const Node &a, const Node &b) const + { return static_cast(*this)(a.m_data, b.m_data); } + + bool operator()(const Node &a) const + { return static_cast(*this)(a.m_data); } + }; + /// @endcond + public: + //! The type of object, T, stored in the list + typedef T value_type; + //! Pointer to T + typedef typename A::pointer pointer; + //! Const pointer to T + typedef typename A::const_pointer const_pointer; + //! Reference to T + typedef typename A::reference reference; + //! Const reference to T + typedef typename A::const_reference const_reference; + //! An unsigned integral type + typedef typename A::size_type size_type; + //! A signed integral type + typedef typename A::difference_type difference_type; + //! The allocator type + typedef A allocator_type; + //! 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 + + public: + + //! Const iterator used to iterate through a list. + class const_iterator + /// @cond + : public std::iterator + { + + 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; + 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; + 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; } + + iterator operator++(int) + { typename Icont::iterator tmp = this->m_it; ++*this; return iterator(tmp); } + } + /// @endcond + ; + + public: + //! Effects: Constructs a list taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + explicit slist(const allocator_type& a = allocator_type()) + : AllocHolder(a) + {} + + explicit slist(size_type n) + : AllocHolder(allocator_type()) + { this->resize(n); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: 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); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts a copy of the range [first, last) in the list. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's constructor taking an dereferenced InIt throws. + //! + //! Complexity: Linear to the range [first, last). + template + slist(InpIt first, InpIt last, + const allocator_type& a = allocator_type()) + : AllocHolder(a) + { this->insert_after(this->before_begin(), first, last); } + + //! Effects: Copy constructs a list. + //! + //! Postcondition: x == *this. + //! + //! Throws: If allocator_type's default constructor or copy constructor throws. + //! + //! Complexity: Linear to the elements x contains. + slist(const slist& x) + : AllocHolder(x) + { this->insert_after(this->before_begin(), x.begin(), x.end()); } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + slist(BOOST_RV_REF(slist) x) + : AllocHolder(boost::move((AllocHolder&)x)) + {} + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + slist& operator= (BOOST_COPY_ASSIGN_REF(slist) x) + { + if (&x != this){ + this->assign(x.begin(), x.end()); + } + return *this; + } + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + slist& operator= (BOOST_RV_REF(slist) mx) + { + if (&mx != this){ + this->clear(); + this->swap(mx); + } + return *this; + } + + //! Effects: Destroys the list. All stored values are destroyed + //! and used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements. + ~slist() + {} //AllocHolder clears the slist + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return allocator_type(this->node_alloc()); } + + const stored_allocator_type &get_stored_allocator() const + { return this->node_alloc(); } + + stored_allocator_type &get_stored_allocator() + { return this->node_alloc(); } + + public: + + //! Effects: Assigns the n copies of val to *this. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void assign(size_type n, const T& val) + { this->priv_fill_assign(n, val); } + + //! Effects: Assigns the range [first, last) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! Complexity: Linear to n. + template + void assign(InpIt first, InpIt last) + { + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_assign_dispatch(first, last, Result()); + } + + //! Effects: Returns an iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return iterator(this->icont().begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return this->cbegin(); } + + //! Effects: Returns an iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return iterator(this->icont().end()); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return this->cend(); } + + //! Effects: Returns a non-dereferenceable iterator that, + //! when incremented, yields begin(). This iterator may be used + //! as the argument toinsert_after, erase_after, etc. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator before_begin() + { return iterator(end()); } + + //! Effects: Returns a non-dereferenceable const_iterator + //! that, when incremented, yields begin(). This iterator may be used + //! as the argument toinsert_after, erase_after, etc. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator before_begin() const + { return this->cbefore_begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return const_iterator(this->non_const_icont().begin()); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return const_iterator(this->non_const_icont().end()); } + + //! Effects: Returns a non-dereferenceable const_iterator + //! that, when incremented, yields begin(). This iterator may be used + //! as the argument toinsert_after, erase_after, etc. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbefore_begin() const + { return const_iterator(end()); } + + //! Effects: Returns the number of the elements contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return this->icont().size(); } + + //! Effects: Returns the largest possible size of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return AllocHolder::max_size(); } + + //! Effects: Returns true if the list contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return !this->size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() + //! allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements on *this and x. + void swap(slist& x) + { AllocHolder::swap(x); } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference front() + { return *this->begin(); } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference front() const + { return *this->begin(); } + + //! Effects: Inserts a copy of t in the beginning of the list. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_front(insert_const_ref_type x) + { return priv_push_front(x); } + + #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + void push_front(T &x) { push_front(const_cast(x)); } + + template + void push_front(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return priv_push_front(u); } + #endif + + //! Effects: Constructs a new element in the beginning of the list + //! and moves the resources of t to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + void push_front(BOOST_RV_REF(T) x) + { this->icont().push_front(*this->create_node(boost::move(x))); } + + //! Effects: Removes the first element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + void pop_front() + { this->icont().pop_front_and_dispose(Destroyer(this->node_alloc())); } + + //! Returns: 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. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + iterator previous(iterator p) + { return iterator(this->icont().previous(p.get())); } + + //! Returns: 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. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + const_iterator previous(const_iterator p) + { return const_iterator(this->icont().previous(p.get())); } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Inserts a copy of the value after the p pointed + //! by prev_p. + //! + //! Returns: An iterator to the inserted element. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + //! + //! Note: 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(x)); } + + template + iterator insert_after(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return this->priv_insert_after(position, u); } + #endif + + //! Requires: prev_pos must be a valid iterator of *this. + //! + //! Effects: Inserts a move constructed copy object from the value after the + //! p pointed by prev_pos. + //! + //! Returns: An iterator to the inserted element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + //! + //! Note: 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)))); } + + //! Requires: prev_pos must be a valid iterator of *this. + //! + //! Effects: Inserts n copies of x after prev_pos. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + //! + //! Note: 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); } + + //! Requires: prev_pos must be a valid iterator of *this. + //! + //! Effects: Inserts the range pointed by [first, last) + //! after the p prev_pos. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws. + //! + //! Complexity: Linear to the number of elements inserted. + //! + //! Note: Does not affect the validity of iterators and references of + //! previous values. + template + void insert_after(const_iterator prev_pos, InIter first, InIter last) + { + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_insert_after_range_dispatch(prev_pos, first, last, Result()); + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of x before p. + //! + //! Throws: If memory allocation throws or x's copy constructor throws. + //! + //! Complexity: 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(x)); } + + template + iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return this->priv_insert(position, u); } + #endif + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a new element before p with mx's resources. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: 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)); } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Inserts n copies of x before p. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: 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); } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [first, last) range before p. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws. + //! + //! Complexity: Linear to std::distance [first, last) plus + //! linear to the elements before p. + template + void insert(const_iterator p, InIter first, InIter last) + { return this->insert_after(previous(p), first, last); } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the front of the list + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + template + void emplace_front(Args&&... args) + { this->emplace_after(this->cbefore_begin(), boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... before p + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Linear to the elements before p + template + iterator emplace(const_iterator p, Args&&... args) + { return this->emplace_after(this->previous(p), boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... after prev + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Constant + template + iterator emplace_after(const_iterator prev, Args&&... args) + { + typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator()); + new ((void*)containers_detail::get_pointer(d.get())) Node(boost::forward(args)...); + NodePtr node = d.get(); + d.release(); + return iterator(this->icont().insert_after(prev.get(), *node)); + } + + #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //0 args + void emplace_front() + { this->emplace_after(this->cbefore_begin()); } + + iterator emplace(const_iterator p) + { return this->emplace_after(this->previous(p)); } + + iterator emplace_after(const_iterator prev) + { + typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator()); + new ((void*)containers_detail::get_pointer(d.get())) Node(); + NodePtr node = d.get(); + d.release(); + return iterator(this->icont().insert_after(prev.get(), *node)); + } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + this->emplace \ + (this->cbegin(), BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + } \ + \ + template \ + iterator emplace \ + (const_iterator p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + return this->emplace_after \ + (this->previous(p), BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + } \ + \ + template \ + iterator emplace_after \ + (const_iterator prev, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator()); \ + new ((void*)containers_detail::get_pointer(d.get())) \ + Node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + NodePtr node = d.get(); \ + d.release(); \ + return iterator(this->icont().insert_after(prev.get(), *node)); \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Erases the element after the element pointed by prev_pos + //! of the list. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not invalidate iterators or references to non erased elements. + iterator erase_after(const_iterator prev_pos) + { + return iterator(this->icont().erase_after_and_dispose(prev_pos.get(), Destroyer(this->node_alloc()))); + } + + //! Effects: Erases the range (before_first, last) from + //! the list. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of erased elements. + //! + //! Note: Does not invalidate iterators or references to non erased elements. + iterator erase_after(const_iterator before_first, const_iterator last) + { + return iterator(this->icont().erase_after_and_dispose(before_first.get(), last.get(), Destroyer(this->node_alloc()))); + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Erases the element at p p. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before p. + iterator erase(const_iterator p) + { return iterator(this->erase_after(previous(p))); } + + //! Requires: first and last must be valid iterator to elements in *this. + //! + //! Effects: Erases the elements pointed by [first, last). + //! + //! Throws: Nothing. + //! + //! Complexity: 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)); } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: 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); + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default constructed. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size) + { + 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); + } + } + + //! Effects: Erases all the elements of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the list. + void clear() + { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); } + + //! Requires: p must point to an element contained + //! by the list. x != *this + //! + //! Effects: Transfers all the elements of list x to this list, after the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear to the elements in x. + //! + //! Note: 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"); + } + } + + //! Requires: prev_pos must be a valid iterator of this. + //! i must point to an element contained in list x. + //! + //! Effects: 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. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Constant. + //! + //! Note: 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) + { + 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"); + } + } + + //! Requires: 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. + //! + //! Effects: Transfers the range [before_first + 1, before_last + 1) + //! from list x to this list, after the element pointed by prev_pos. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear to the number of transferred elements. + //! + //! Note: 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"); + } + } + + //! Requires: 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. + //! n == std::distance(before_first, before_last) + //! + //! Effects: Transfers the range [before_first + 1, before_last + 1) + //! from list x to this list, after the element pointed by prev_pos. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Constant. + //! + //! Note: 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) + { + 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"); + } + } + + //! Requires: p must point to an element contained + //! by the list. x != *this + //! + //! Effects: Transfers all the elements of list x to this list, before the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear in distance(begin(), p), and linear in x.size(). + //! + //! Note: 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); } + + //! Requires: p must point to an element contained + //! by this list. i must point to an element contained in list x. + //! + //! Effects: 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. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear in distance(begin(), p), and in distance(x.begin(), i). + //! + //! Note: 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); } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! + //! Effects: 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. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear in distance(begin(), p), in distance(x.begin(), first), + //! and in distance(first, last). + //! + //! Note: 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)); } + + //! Effects: Reverses the order of elements in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time. + //! + //! Note: Iterators and references are not invalidated + void reverse() + { this->icont().reverse(); } + + //! Effects: Removes all the elements that compare equal to value. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: 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)); } + + //! Effects: Removes all the elements for which a specified + //! predicate is satisfied. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time. It performs exactly size() calls to the predicate. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_if(Pred pred) + { + typedef ValueCompareToNodeCompare Predicate; + this->icont().remove_and_dispose_if(Predicate(pred), Destroyer(this->node_alloc())); + } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that are equal from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear time (size()-1 comparisons calls to pred()). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void unique() + { this->unique(value_equal()); } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time (size()-1 comparisons equality comparisons). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique(Pred pred) + { + typedef ValueCompareToNodeCompare Predicate; + this->icont().unique_and_dispose(Predicate(pred), Destroyer(this->node_alloc())); + } + + //! Requires: The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this according to std::less. 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. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + void merge(slist & x) + { this->merge(x, value_less()); } + + //! Requires: 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. + //! + //! Effects: 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. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references to *this are not invalidated. + template + void merge(slist& x, StrictWeakOrdering comp) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().merge(x.icont(), + ValueCompareToNodeCompare(comp)); + } + else{ + throw std::runtime_error("list::merge called with unequal allocators"); + } + } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: Nothing. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + void sort() + { this->sort(value_less()); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: Nothing. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + template + void sort(StrictWeakOrdering comp) + { + // nothing if the slist has length 0 or 1. + if (this->size() < 2) + return; + this->icont().sort(ValueCompareToNodeCompare(comp)); + } + + /// @cond + private: + iterator priv_insert(const_iterator p, const value_type& x) + { return this->insert_after(previous(p), x); } + + 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))); } + + void priv_push_front(const value_type &x) + { this->icont().push_front(*this->create_node(x)); } + + //Iterator range version + template + void priv_create_and_insert_nodes + (const_iterator prev, InpIterator beg, InpIterator end) + { + typedef typename std::iterator_traits::iterator_category ItCat; + priv_create_and_insert_nodes(prev, beg, end, alloc_version(), ItCat()); + } + + template + void priv_create_and_insert_nodes + (const_iterator prev, InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag) + { + for (; beg != end; ++beg){ + this->icont().insert_after(prev.get(), *this->create_node_from_it(beg)); + ++prev; + } + } + + template + 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()); + } + + class insertion_functor; + friend class insertion_functor; + + class insertion_functor + { + Icont &icont_; + typename Icont::const_iterator prev_; + + public: + insertion_functor(Icont &icont, typename Icont::const_iterator prev) + : icont_(icont), prev_(prev) + {} + + void operator()(Node &n) + { prev_ = this->icont_.insert_after(prev_, n); } + }; + + template + 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())); + } + + //Default constructed version + void priv_create_and_insert_nodes(const_iterator prev, size_type n) + { + typedef default_construct_iterator default_iterator; + this->priv_create_and_insert_nodes(prev, default_iterator(n), default_iterator()); + } + + //Copy constructed version + void priv_create_and_insert_nodes(const_iterator prev, size_type n, const T& x) + { + typedef constant_iterator cvalue_iterator; + this->priv_create_and_insert_nodes(prev, cvalue_iterator(x, n), cvalue_iterator()); + } + + //Dispatch to detect iterator range or integer overloads + template + void priv_insert_dispatch(const_iterator prev, + InputIter first, InputIter last, + containers_detail::false_) + { this->priv_create_and_insert_nodes(prev, first, last); } + + template + void priv_insert_dispatch(const_iterator prev, Integer n, Integer x, containers_detail::true_) + { this->priv_create_and_insert_nodes(prev, (size_type)n, x); } + + void priv_fill_assign(size_type n, const T& val) + { + 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; + } + if (n > 0) + this->priv_create_and_insert_nodes(prev, n, val); + else + this->erase_after(prev, end_n); + } + + template + void priv_assign_dispatch(Int n, Int val, containers_detail::true_) + { this->priv_fill_assign((size_type) n, (T)val); } + + template + void priv_assign_dispatch(InpIt first, InpIt last, containers_detail::false_) + { + 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); + } + + template + void priv_insert_after_range_dispatch(const_iterator prev_pos, Int n, Int x, containers_detail::true_) + { this->priv_create_and_insert_nodes(prev_pos, (size_type)n, x); } + + template + void priv_insert_after_range_dispatch(const_iterator prev_pos, InIter first, InIter last, containers_detail::false_) + { this->priv_create_and_insert_nodes(prev_pos, first, last); } + + //Functors for member algorithm defaults + struct value_less + { + bool operator()(const value_type &a, const value_type &b) const + { return a < b; } + }; + + struct value_equal + { + bool operator()(const value_type &a, const value_type &b) const + { return a == b; } + }; + + struct value_equal_to_this + { + explicit value_equal_to_this(const value_type &ref) + : m_ref(ref){} + + bool operator()(const value_type &val) const + { return m_ref == val; } + + const value_type &m_ref; + }; + /// @endcond +}; + +template +inline bool +operator==(const slist& x, const slist& y) +{ + if(x.size() != y.size()){ + return false; + } + typedef typename slist::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 +inline bool +operator<(const slist& sL1, const slist& sL2) +{ + return std::lexicographical_compare + (sL1.begin(), sL1.end(), sL2.begin(), sL2.end()); +} + +template +inline bool +operator!=(const slist& sL1, const slist& sL2) + { return !(sL1 == sL2); } + +template +inline bool +operator>(const slist& sL1, const slist& sL2) + { return sL2 < sL1; } + +template +inline bool +operator<=(const slist& sL1, const slist& sL2) + { return !(sL2 < sL1); } + +template +inline bool +operator>=(const slist& sL1, const slist& sL2) + { return !(sL1 < sL2); } + +template +inline void swap(slist& x, slist& y) + { x.swap(y); } + +}} + +/// @cond + +namespace boost { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value; +}; +*/ +namespace container { + +/// @endcond + +}} //namespace boost{ namespace container { + +// Specialization of insert_iterator so that insertions will be constant +// time rather than linear time. + +///@cond + +//Ummm, I don't like to define things in namespace std, but +//there is no other way +namespace std { + +template +class insert_iterator > +{ + protected: + typedef boost::container::slist Container; + Container* container; + typename Container::iterator iter; + public: + typedef Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(Container& x, + typename Container::iterator i, + bool is_previous = false) + : container(&x), iter(is_previous ? i : x.previous(i)){ } + + insert_iterator& + operator=(const typename Container::value_type& value) + { + iter = container->insert_after(iter, value); + return *this; + } + insert_iterator& operator*(){ return *this; } + insert_iterator& operator++(){ return *this; } + insert_iterator& operator++(int){ return *this; } +}; + +} //namespace std; + +///@endcond + +#include + +#endif /* BOOST_CONTAINERS_SLIST_HPP */ diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp new file mode 100644 index 0000000..eb58007 --- /dev/null +++ b/include/boost/container/stable_vector.hpp @@ -0,0 +1,1697 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +/* Stable vector. + * + * Copyright 2008 Joaquin M Lopez Munoz. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifndef BOOST_CONTAINER_STABLE_VECTOR_HPP +#define BOOST_CONTAINER_STABLE_VECTOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +///@cond + +#include + +//#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING + +#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING) +#include +#endif + +///@endcond + +namespace boost { +namespace container { + +///@cond + +namespace stable_vector_detail{ + +template +struct smart_ptr_type +{ + typedef typename SmartPtr::value_type value_type; + typedef value_type *pointer; + static pointer get (const SmartPtr &smartptr) + { return smartptr.get();} +}; + +template +struct smart_ptr_type +{ + typedef T value_type; + typedef value_type *pointer; + static pointer get (pointer ptr) + { return ptr;} +}; + +template +inline typename smart_ptr_type::pointer get_pointer(const Ptr &ptr) +{ return smart_ptr_type::get(ptr); } + +template +class clear_on_destroy +{ + public: + clear_on_destroy(C &c) + : c_(c), do_clear_(true) + {} + + void release() + { do_clear_ = false; } + + ~clear_on_destroy() + { + if(do_clear_){ + c_.clear(); + c_.clear_pool(); + } + } + + private: + clear_on_destroy(const clear_on_destroy &); + clear_on_destroy &operator=(const clear_on_destroy &); + C &c_; + bool do_clear_; +}; + +template +struct node_type_base +{/* + node_type_base(VoidPtr p) + : up(p) + {}*/ + node_type_base() + {} + void set_pointer(VoidPtr p) + { up = p; } + + VoidPtr up; +}; + +template +struct node_type + : public node_type_base +{ + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + node_type() + : value() + {} + + template + node_type(Args &&...args) + : value(boost::forward(args)...) + {} + + #else //BOOST_CONTAINERS_PERFECT_FORWARDING + + node_type() + : value() + {} + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + node_type(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + : value(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \ + {} \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif//BOOST_CONTAINERS_PERFECT_FORWARDING + + void set_pointer(VoidPointer p) + { node_type_base::set_pointer(p); } + + T value; +}; + +template +class iterator + : public std::iterator< std::random_access_iterator_tag + , typename std::iterator_traits::value_type + , typename std::iterator_traits::difference_type + , Pointer + , Reference> +{ + + typedef typename boost::pointer_to_other + ::type void_ptr; + typedef typename boost::pointer_to_other + ::type const_void_ptr; + typedef node_type node_type_t; + typedef typename boost::pointer_to_other + ::type node_type_ptr_t; + typedef typename boost::pointer_to_other + ::type const_node_type_ptr_t; + typedef typename boost::pointer_to_other + ::type void_ptr_ptr; + + friend class iterator::type>; + + public: + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef typename std::iterator_traits + ::difference_type difference_type; + typedef Pointer pointer; + typedef Reference reference; + + iterator() + {} + + explicit iterator(node_type_ptr_t pn) + : pn(pn) + {} + + iterator(const iterator::type >& x) + : pn(x.pn) + {} + + private: + static node_type_ptr_t node_ptr_cast(const void_ptr &p) + { + using boost::get_pointer; + return node_type_ptr_t(static_cast(stable_vector_detail::get_pointer(p))); + } + + static const_node_type_ptr_t node_ptr_cast(const const_void_ptr &p) + { + using boost::get_pointer; + return const_node_type_ptr_t(static_cast(stable_vector_detail::get_pointer(p))); + } + + static void_ptr_ptr void_ptr_ptr_cast(const void_ptr &p) + { + using boost::get_pointer; + return void_ptr_ptr(static_cast(stable_vector_detail::get_pointer(p))); + } + + 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); } + + 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; } + + iterator operator++(int) + { iterator tmp(*this); ++*this; return iterator(tmp); } + + iterator& operator--() + { this->decrement(); return *this; } + + iterator operator--(int) + { iterator tmp(*this); --*this; return iterator(tmp); } + + reference operator[](difference_type off) const + { + iterator tmp(*this); + tmp += off; + return *tmp; + } + + iterator& operator+=(difference_type off) + { + pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+off)); + return *this; + } + + friend iterator operator+(const iterator &left, difference_type off) + { + iterator tmp(left); + tmp += off; + return tmp; + } + + friend iterator operator+(difference_type off, const iterator& right) + { + iterator tmp(right); + tmp += off; + return tmp; + } + + iterator& operator-=(difference_type off) + { *this += -off; return *this; } + + friend iterator operator-(const iterator &left, difference_type off) + { + 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); + } + + //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 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); } + + node_type_ptr_t pn; +}; + +template +struct select_multiallocation_chain +{ + typedef typename A::multiallocation_chain type; +}; + +template +struct select_multiallocation_chain +{ + typedef typename A::template + rebind::other::pointer void_ptr; + typedef containers_detail::basic_multiallocation_chain + multialloc_cached_counted; + typedef boost::container::containers_detail::transform_multiallocation_chain + type; +}; + +} //namespace stable_vector_detail + +#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING) + +#define STABLE_VECTOR_CHECK_INVARIANT \ +invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \ +BOOST_JOIN(check_invariant_,__LINE__).touch(); +#else + +#define STABLE_VECTOR_CHECK_INVARIANT + +#endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING) + +/// @endcond + +//!Originally developed by Joaquin M. Lopez Munoz, stable_vector is std::vector +//!drop-in replacement implemented as a node container, offering iterator and reference +//!stability. +//! +//!More details taken the author's blog: ( Introducing stable_vector) +//! +//!We present stable_vector, a fully STL-compliant stable container that provides +//!most of the features of std::vector except element contiguity. +//! +//!General properties: stable_vector satisfies all the requirements of a container, +//!a reversible container and a sequence and provides all the optional operations +//!present in std::vector. Like std::vector, iterators are random access. +//!stable_vector does not provide element contiguity; in exchange for this absence, +//!the container is stable, i.e. references and iterators to an element of a stable_vector +//!remain valid as long as the element is not erased, and an iterator that has been +//!assigned the return value of end() always remain valid until the destruction of +//!the associated stable_vector. +//! +//!Operation complexity: The big-O complexities of stable_vector operations match +//!exactly those of std::vector. In general, insertion/deletion is constant time at +//!the end of the sequence and linear elsewhere. Unlike std::vector, stable_vector +//!does not internally perform any value_type destruction, copy or assignment +//!operations other than those exactly corresponding to the insertion of new +//!elements or deletion of stored elements, which can sometimes compensate in terms +//!of performance for the extra burden of doing more pointer manipulation and an +//!additional allocation per element. +//! +//!Exception safety: As stable_vector does not internally copy elements around, some +//!operations provide stronger exception safety guarantees than in std::vector: +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template > +#else +template +#endif +class stable_vector +{ + ///@cond + typedef typename containers_detail:: + move_const_ref_type::type insert_const_ref_type; + typedef typename A::template + rebind::other::pointer void_ptr; + typedef typename boost::pointer_to_other + ::type const_void_ptr; + typedef typename A::template + rebind::other::pointer void_ptr_ptr; + typedef typename boost::pointer_to_other + ::type const_void_ptr_ptr; + typedef stable_vector_detail::node_type + node_type_t; + typedef typename A::template + rebind::other::pointer node_type_ptr_t; + typedef stable_vector_detail::node_type_base + node_type_base_t; + typedef typename A::template + rebind::other::pointer node_type_base_ptr_t; + typedef + ::boost::container::vector::other + > impl_type; + typedef typename impl_type::iterator impl_iterator; + typedef typename impl_type::const_iterator const_impl_iterator; + + typedef ::boost::container::containers_detail:: + integral_constant allocator_v1; + typedef ::boost::container::containers_detail:: + integral_constant allocator_v2; + typedef ::boost::container::containers_detail::integral_constant + ::value> alloc_version; + typedef typename A:: + template rebind::other node_allocator_type; + + node_type_ptr_t allocate_one() + { return this->allocate_one(alloc_version()); } + + node_type_ptr_t allocate_one(allocator_v1) + { return get_al().allocate(1); } + + node_type_ptr_t allocate_one(allocator_v2) + { return get_al().allocate_one(); } + + void deallocate_one(node_type_ptr_t p) + { return this->deallocate_one(p, alloc_version()); } + + void deallocate_one(node_type_ptr_t p, allocator_v1) + { get_al().deallocate(p, 1); } + + void deallocate_one(node_type_ptr_t p, allocator_v2) + { get_al().deallocate_one(p); } + + friend class stable_vector_detail::clear_on_destroy; + ///@endcond + public: + + + // types: + + typedef typename A::reference reference; + typedef typename A::const_reference const_reference; + typedef typename A::pointer pointer; + typedef typename A::const_pointer const_pointer; + typedef stable_vector_detail::iterator + iterator; + typedef stable_vector_detail::iterator + 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 reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + ///@cond + 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 + public: + + //! Effects: Constructs a stable_vector taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + explicit stable_vector(const A& al=A()) + : internal_data(al),impl(al) + { + STABLE_VECTOR_CHECK_INVARIANT; + } + + //! Effects: Constructs a stable_vector that will use a copy of allocator a + //! and inserts n default contructed values. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + explicit stable_vector(size_type n) + : internal_data(A()),impl(A()) + { + stable_vector_detail::clear_on_destroy cod(*this); + this->resize(n); + STABLE_VECTOR_CHECK_INVARIANT; + cod.release(); + } + + //! Effects: Constructs a stable_vector that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + stable_vector(size_type n, const T& t, const A& al=A()) + : internal_data(al),impl(al) + { + stable_vector_detail::clear_on_destroy cod(*this); + this->insert(this->cbegin(), n, t); + STABLE_VECTOR_CHECK_INVARIANT; + cod.release(); + } + + //! Effects: 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. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's constructor taking an dereferenced InIt throws. + //! + //! Complexity: Linear to the range [first, last). + template + stable_vector(InputIterator first,InputIterator last,const A& al=A()) + : internal_data(al),impl(al) + { + stable_vector_detail::clear_on_destroy cod(*this); + this->insert(this->cbegin(), first, last); + STABLE_VECTOR_CHECK_INVARIANT; + cod.release(); + } + + //! Effects: Copy constructs a stable_vector. + //! + //! Postcondition: x == *this. + //! + //! Complexity: Linear to the elements x contains. + stable_vector(const stable_vector& x) + : internal_data(x.get_al()),impl(x.get_al()) + { + stable_vector_detail::clear_on_destroy cod(*this); + this->insert(this->cbegin(), x.begin(), x.end()); + STABLE_VECTOR_CHECK_INVARIANT; + cod.release(); + } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + stable_vector(BOOST_RV_REF(stable_vector) x) + : internal_data(x.get_al()),impl(x.get_al()) + { this->swap(x); } + + //! Effects: Destroys the stable_vector. All stored values are destroyed + //! and used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements. + ~stable_vector() + { + this->clear(); + clear_pool(); + } + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x) + { + STABLE_VECTOR_CHECK_INVARIANT; + if (this != &x) { + this->assign(x.begin(), x.end()); + } + return *this; + } + + //! Effects: Move assignment. All mx's values are transferred to *this. + //! + //! Postcondition: x.empty(). *this contains a the elements x had + //! before the function. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Linear. + stable_vector& operator=(BOOST_RV_REF(stable_vector) x) + { + if (&x != this){ + this->swap(x); + x.clear(); + } + return *this; + } + + //! Effects: Assigns the the range [first, last) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! Complexity: Linear to n. + template + void assign(InputIterator first,InputIterator last) + { + assign_dispatch(first, last, boost::is_integral()); + } + + + //! Effects: Assigns the n copies of val to *this. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void assign(size_type n,const T& t) + { + typedef constant_iterator cvalue_iterator; + return assign_dispatch(cvalue_iterator(t, n), cvalue_iterator(), boost::mpl::false_()); + } + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + allocator_type get_allocator()const {return get_al();} + + + //! Effects: Returns an iterator to the first element contained in the stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return (impl.empty()) ? end(): iterator(node_ptr_cast(impl.front())) ; } + + //! Effects: Returns a const_iterator to the first element contained in the stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin()const + { return (impl.empty()) ? cend() : const_iterator(node_ptr_cast(impl.front())) ; } + + //! Effects: Returns an iterator to the end of the stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() {return iterator(get_end_node());} + + //! Effects: Returns a const_iterator to the end of the stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end()const {return const_iterator(get_end_node());} + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() {return reverse_iterator(this->end());} + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin()const {return const_reverse_iterator(this->end());} + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() {return reverse_iterator(this->begin());} + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend()const {return const_reverse_iterator(this->begin());} + + //! Effects: Returns a const_iterator to the first element contained in the stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin()const {return this->begin();} + + //! Effects: Returns a const_iterator to the end of the stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend()const {return this->end();} + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin()const{return this->rbegin();} + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend()const {return this->rend();} + + //! Effects: Returns the number of the elements contained in the stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return impl.empty() ? 0 : (impl.size() - ExtraPointers); } + + //! Effects: Returns the largest possible size of the stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return impl.max_size() - ExtraPointers; } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { + 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; + } + } + + //! Effects: Returns true if the stable_vector contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return impl.empty() || impl.size() == ExtraPointers; } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type n, const T& t) + { + STABLE_VECTOR_CHECK_INVARIANT; + if(n > size()) + this->insert(this->cend(), n - this->size(), t); + else if(n < this->size()) + this->erase(this->cbegin() + n, this->cend()); + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default constructed. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type n) + { + typedef default_construct_iterator default_iterator; + STABLE_VECTOR_CHECK_INVARIANT; + if(n > size()) + this->insert(this->cend(), default_iterator(n - this->size()), default_iterator()); + else if(n < this->size()) + this->erase(this->cbegin() + n, this->cend()); + } + + //! Effects: 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. + //! + //! Throws: If memory allocation allocation throws. + void reserve(size_type n) + { + STABLE_VECTOR_CHECK_INVARIANT; + if(n > this->max_size()) + throw std::bad_alloc(); + + size_type size = 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; + //Fix the pointers for the newly allocated buffer + if(realloced){ + this->align_nodes(impl.begin(), impl.begin()+size+1); + } + //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); + } + } + } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference operator[](size_type n){return value(impl[n]);} + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference operator[](size_type n)const{return value(impl[n]);} + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + reference at(size_type n) + { + if(n>=size()) + throw std::out_of_range("invalid subscript at stable_vector::at"); + return operator[](n); + } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: 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); + } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference front() + { return value(impl.front()); } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference front()const + { return value(impl.front()); } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the last + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference back() + { return value(*(&impl.back() - ExtraPointers)); } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the last + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference back()const + { return value(*(&impl.back() - ExtraPointers)); } + + //! Effects: Inserts a copy of x at the end of the stable_vector. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: 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(x)); } + + template + void push_back(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return priv_push_back(u); } + #endif + + //! Effects: Constructs a new element in the end of the stable_vector + //! and moves the resources of mx to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + void push_back(BOOST_RV_REF(T) t) + { this->insert(end(), boost::move(t)); } + + //! Effects: Removes the last element from the stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + void pop_back() + { this->erase(this->end()-1); } + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Insert a copy of x before position. + //! + //! Throws: If memory allocation throws or x's copy constructor throws. + //! + //! Complexity: 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(x)); } + + template + iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0) + { return this->priv_insert(position, u); } + #endif + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Insert a new element before position with mx's resources. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: If position is end(), amortized constant time + //! Linear time otherwise. + iterator insert(const_iterator position, BOOST_RV_REF(T) x) + { + typedef repeat_iterator repeat_it; + typedef boost::move_iterator 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); + } + + //! Requires: pos must be a valid iterator of *this. + //! + //! Effects: Insert n copies of x before pos. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void insert(const_iterator position, size_type n, const T& t) + { + STABLE_VECTOR_CHECK_INVARIANT; + this->insert_not_iter(position, n, t); + } + + //! Requires: pos must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [first, last) range before pos. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws or T's copy constructor throws. + //! + //! Complexity: Linear to std::distance [first, last). + template + void insert(const_iterator position,InputIterator first, InputIterator last) + { + STABLE_VECTOR_CHECK_INVARIANT; + this->insert_iter(position,first,last, + boost::mpl::not_ >()); + } + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the end of the stable_vector. + //! + //! Throws: If memory allocation throws or the in-place constructor throws. + //! + //! Complexity: Amortized constant time. + template + void emplace_back(Args &&...args) + { + typedef emplace_functor EmplaceFunctor; + typedef emplace_iterator EmplaceIterator; + EmplaceFunctor &&ef = EmplaceFunctor(boost::forward(args)...); + this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator()); + } + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... before position + //! + //! Throws: If memory allocation throws or the in-place constructor throws. + //! + //! Complexity: If position is end(), amortized constant time + //! Linear time otherwise. + template + 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 emplace_functor EmplaceFunctor; + typedef emplace_iterator EmplaceIterator; + EmplaceFunctor &&ef = EmplaceFunctor(boost::forward(args)...); + this->insert(position, EmplaceIterator(ef), EmplaceIterator()); + return iterator(this->begin() + pos_n); + } + + #else + + void emplace_back() + { + typedef emplace_functor EmplaceFunctor; + typedef emplace_iterator EmplaceIterator; + EmplaceFunctor ef; + this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator()); + } + + iterator emplace(const_iterator position) + { + typedef emplace_functor EmplaceFunctor; + typedef emplace_iterator EmplaceIterator; + EmplaceFunctor ef; + size_type pos_n = position - this->cbegin(); + this->insert(position, EmplaceIterator(ef), EmplaceIterator()); + return iterator(this->begin() + pos_n); + } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \ + EmplaceFunctor; \ + typedef emplace_iterator EmplaceIterator; \ + EmplaceFunctor ef(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator()); \ + } \ + \ + template \ + iterator emplace(const_iterator pos, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \ + EmplaceFunctor; \ + typedef emplace_iterator EmplaceIterator; \ + EmplaceFunctor ef(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + size_type pos_n = pos - this->cbegin(); \ + this->insert(pos, EmplaceIterator(ef), EmplaceIterator()); \ + return iterator(this->begin() + pos_n); \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Erases the element at position pos. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements between pos and the + //! last element. Constant if pos is the last element. + iterator erase(const_iterator position) + { + 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; + } + + //! Effects: Erases the elements pointed by [first, last). + //! + //! Throws: Nothing. + //! + //! Complexity: 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()); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() + //! allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(stable_vector & x) + { + STABLE_VECTOR_CHECK_INVARIANT; + this->swap_impl(*this,x); + } + + //! Effects: Erases all the elements of the stable_vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the stable_vector. + void clear() + { this->erase(this->cbegin(),this->cend()); } + + //! Effects: Tries to deallocate the excess of memory created + //! with previous allocations. The size of the stable_vector is unchanged + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: 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()){ + impl_type().swap(this->impl); + 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); + } + } + } + } + + /// @cond + + iterator priv_insert(const_iterator position, const value_type &t) + { + typedef constant_iterator cvalue_iterator; + return this->insert_iter(position, cvalue_iterator(t, 1), cvalue_iterator(), std::forward_iterator_tag()); + } + + void priv_push_back(const value_type &t) + { this->insert(end(), t); } + + void clear_pool(allocator_v1) + { + 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, 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; + } + } + + void clear_pool(allocator_v2) + { + + 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); + get_al().deallocate_individual(boost::move(holder)); + pool_first_ref = pool_last_ref = 0; + this->internal_data.pool_size = 0; + } + } + + void clear_pool() + { + this->clear_pool(alloc_version()); + } + + void add_to_pool(size_type n) + { + this->add_to_pool(n, alloc_version()); + } + + void add_to_pool(size_type n, allocator_v1) + { + size_type remaining = n; + while(remaining--){ + this->put_in_pool(this->allocate_one()); + } + } + + void add_to_pool(size_type n, allocator_v2) + { + 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::value == true)); + multiallocation_chain m (get_al().allocate_individual(n)); + holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n); + this->internal_data.pool_size += n; + std::pair data(holder.extract_data()); + pool_first_ref = data.first; + pool_last_ref = data.second; + } + + void put_in_pool(node_type_ptr_t p) + { + 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 ret(holder.extract_data()); + pool_first_ref = ret.first; + pool_last_ref = ret.second; + } + + 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 data(holder.extract_data()); + pool_first_ref = data.first; + pool_last_ref = data.second; + } + 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); + } + } + + template + void assign_dispatch(InputIterator first, InputIterator last, boost::mpl::false_) + { + 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); + } + } + + template + void assign_dispatch(Integer n, Integer t, boost::mpl::true_) + { + typedef constant_iterator cvalue_iterator; + this->assign_dispatch(cvalue_iterator(t, n), cvalue_iterator(), boost::mpl::false_()); + } + + iterator priv_erase(const_iterator first, const_iterator last, allocator_v1) + { + 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()); + } + return iterator(this->begin() + d1); + } + + impl_iterator get_last_align() + { + return impl.end() - (ExtraPointers - 1); + } + + const_impl_iterator get_last_align() const + { + return impl.cend() - (ExtraPointers - 1); + } + + template + iterator priv_erase(const_iterator first, const_iterator last, AllocatorVersion, + typename boost::container::containers_detail::enable_if_c + + ::value>::type * = 0) + { + STABLE_VECTOR_CHECK_INVARIANT; + return priv_erase(first, last, allocator_v1()); + } + + static node_type_ptr_t node_ptr_cast(const void_ptr &p) + { + using boost::get_pointer; + return node_type_ptr_t(static_cast(stable_vector_detail::get_pointer(p))); + } + + static node_type_base_ptr_t node_base_ptr_cast(const void_ptr &p) + { + using boost::get_pointer; + return node_type_base_ptr_t(static_cast(stable_vector_detail::get_pointer(p))); + } + + static value_type& value(const void_ptr &p) + { + return node_ptr_cast(p)->value; + } + + void initialize_end_node(size_type impl_capacity = 0) + { + 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]; + } + } + + void readjust_end_node() + { + 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; + } + else{ + this->internal_data.end_node.up = void_ptr(&this->internal_data.end_node.up); + } + } + + 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(cp); + return node_ptr_cast(p); + } + + template + void_ptr new_node(const void_ptr &up, Iter it) + { + node_type_ptr_t p = this->allocate_one(); + try{ + boost::container::construct_in_place(&*p, it); + 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)); + n->~node_type_t(); + this->put_in_pool(n); + } + + static void align_nodes(impl_iterator first, impl_iterator last) + { + while(first!=last){ + node_ptr_cast(*first)->up = void_ptr(&*first); + ++first; + } + } + + void insert_not_iter(const_iterator position, size_type n, const T& t) + { + typedef constant_iterator cvalue_iterator; + this->insert_iter(position, cvalue_iterator(t, n), cvalue_iterator(), std::forward_iterator_tag()); + } + + template + void insert_iter(const_iterator position,InputIterator first,InputIterator last, boost::mpl::true_) + { + typedef typename std::iterator_traits::iterator_category category; + this->insert_iter(position, first, last, category()); + } + + template + void insert_iter(const_iterator position,InputIterator first,InputIterator last,std::input_iterator_tag) + { + for(; first!=last; ++first){ + this->insert(position, *first); + } + } + + template + 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; + } + + template + void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v1) + { + 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 + void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v2) + { + multiallocation_chain mem(get_al().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(&*p, first); + p->set_pointer(void_ptr_ptr(&it[i])); + ++first; + it[i] = p; + ++i; + } + } + catch(...){ + get_al().deallocate_one(p); + get_al().deallocate_many(boost::move(mem)); + impl_iterator e = impl.erase(it+i, it+n); + this->align_nodes(e, get_last_align()); + throw; + } + } + + template + 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 = 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(&*p, first); + 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; + } + } + + template + void insert_iter(const_iterator position, InputIterator first, InputIterator last, boost::mpl::false_) + { + this->insert_not_iter(position, first, last); + } + + static void swap_impl(stable_vector& x,stable_vector& y) + { + using std::swap; + swap(x.get_al(),y.get_al()); + swap(x.impl,y.impl); + swap(x.internal_data.pool_size, y.internal_data.pool_size); + x.readjust_end_node(); + y.readjust_end_node(); + } + + #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING) + bool invariant()const + { + if(impl.empty()) + return !capacity() && !size(); + if(get_end_node() != *(impl.end() - ExtraPointers)){ + 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 num_pool = 0; + node_type_ptr_t p = node_ptr_cast(pool_head); + while(p){ + ++num_pool; + p = node_ptr_cast(p->up); + } + return n >= num_pool; + } + + class invariant_checker:private boost::noncopyable + { + const stable_vector* p; + public: + invariant_checker(const stable_vector& v):p(&v){} + ~invariant_checker(){BOOST_ASSERT(p->invariant());} + void touch(){} + }; + #endif + + struct ebo_holder + : node_allocator_type + { + ebo_holder(const allocator_type &a) + : node_allocator_type(a), 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; + } internal_data; + + node_allocator_type &get_al() { return internal_data; } + const node_allocator_type &get_al() const { return internal_data; } + + impl_type impl; + /// @endcond +}; + +template +bool operator==(const stable_vector& x,const stable_vector& y) +{ + return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin()); +} + +template +bool operator< (const stable_vector& x,const stable_vector& y) +{ + return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end()); +} + +template +bool operator!=(const stable_vector& x,const stable_vector& y) +{ + return !(x==y); +} + +template +bool operator> (const stable_vector& x,const stable_vector& y) +{ + return y +bool operator>=(const stable_vector& x,const stable_vector& y) +{ + return !(x +bool operator<=(const stable_vector& x,const stable_vector& y) +{ + return !(x>y); +} + +// specialized algorithms: + +template +void swap(stable_vector& x,stable_vector& y) +{ + x.swap(y); +} + +/// @cond + +#undef STABLE_VECTOR_CHECK_INVARIANT + +/// @endcond + +}} + +#include + +#endif //BOOST_CONTAINER_STABLE_VECTOR_HPP diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp new file mode 100644 index 0000000..8df94ff --- /dev/null +++ b/include/boost/container/string.hpp @@ -0,0 +1,2786 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_STRING_HPP +#define BOOST_CONTAINERS_STRING_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +namespace boost { +namespace container { +#else +namespace boost { +namespace container { +#endif + +/// @cond +namespace containers_detail { +// ------------------------------------------------------------ +// Class basic_string_base. + +// basic_string_base is a helper class that makes it it easier to write +// an exception-safe version of basic_string. The constructor allocates, +// but does not initialize, a block of memory. The destructor +// deallocates, but does not destroy elements within, a block of +// memory. The destructor assumes that the memory either is the internal buffer, +// or else points to a block of memory that was allocated using _String_base's +// allocator and whose size is this->m_storage. +template +class basic_string_base +{ + basic_string_base(); + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_string_base) + + public: + typedef A allocator_type; + //! The stored allocator type + typedef allocator_type stored_allocator_type; + typedef typename A::pointer pointer; + typedef typename A::value_type value_type; + typedef typename A::size_type size_type; + + basic_string_base(const allocator_type& a) + : members_(a) + { 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_(b.members_) + { + init(); + this->swap(b); + } + + ~basic_string_base() + { + this->deallocate_block(); + if(!this->is_short()){ + static_cast(static_cast(&this->members_.m_repr.r))->~long_t(); + } + } + + private: + + //This is the structure controlling a long string + struct long_t + { + size_type is_short : 1; + size_type length : (sizeof(size_type)*CHAR_BIT - 1); + size_type storage; + pointer start; + + long_t() + {} + + long_t(const long_t &other) + { + this->is_short = other.is_short; + length = other.length; + storage = other.storage; + start = other.start; + } + + long_t &operator =(const long_t &other) + { + this->is_short = other.is_short; + length = other.length; + storage = other.storage; + start = other.start; + return *this; + } + }; + + //This type is the first part of the structure controlling a short string + //The "data" member stores + struct short_header + { + unsigned char is_short : 1; + unsigned char length : (CHAR_BIT - 1); + }; + + //This type has the same alignment and size as long_t but it's POD + //so, unlike long_t, it can be placed in a union + + typedef typename boost::aligned_storage< sizeof(long_t), + containers_detail::alignment_of::value>::type long_raw_t; + + protected: + static const size_type MinInternalBufferChars = 8; + static const size_type AlignmentOfValueType = + alignment_of::value; + static const size_type ShortDataOffset = + containers_detail::ct_rounded_size::value; + static const size_type ZeroCostInternalBufferChars = + (sizeof(long_t) - ShortDataOffset)/sizeof(value_type); + static const size_type UnalignedFinalInternalBufferChars = + (ZeroCostInternalBufferChars > MinInternalBufferChars) ? + ZeroCostInternalBufferChars : MinInternalBufferChars; + + struct short_t + { + short_header h; + value_type data[UnalignedFinalInternalBufferChars]; + }; + + union repr_t + { + long_raw_t r; + short_t s; + + short_t &short_repr() const + { return *const_cast(&s); } + + long_t &long_repr() const + { return *const_cast(reinterpret_cast(&r)); } + }; + + struct members_holder + : public A + { + members_holder(const A &a) + : A(a) + {} + + repr_t m_repr; + } members_; + + const A &alloc() const + { return members_; } + + A &alloc() + { return members_; } + + static const size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type); + + private: + + static const size_type MinAllocation = InternalBufferChars*2; + + protected: + bool is_short() const + { return static_cast(this->members_.m_repr.s.h.is_short != 0); } + + void is_short(bool yes) + { + if(yes && !this->is_short()){ + static_cast(static_cast(&this->members_.m_repr.r))->~long_t(); + } + else{ + new(static_cast(&this->members_.m_repr.r))long_t(); + } + this->members_.m_repr.s.h.is_short = yes; + } + + private: + void init() + { + this->members_.m_repr.s.h.is_short = 1; + this->members_.m_repr.s.h.length = 0; + } + + protected: + + typedef containers_detail::integral_constant allocator_v1; + typedef containers_detail::integral_constant allocator_v2; + typedef containers_detail::integral_constant::value> alloc_version; + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, pointer reuse = 0) + { + if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){ + reuse = pointer(0); + command &= ~(expand_fwd | expand_bwd); + } + return this->allocation_command + (command, limit_size, preferred_size, received_size, reuse, alloc_version()); + } + + std::pair + 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(0), false); + received_size = preferred_size; + return std::make_pair(this->alloc().allocate(received_size), false); + } + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, + pointer reuse, + allocator_v2) + { + return this->alloc().allocation_command(command, limit_size, preferred_size, + received_size, reuse); + } + + size_type next_capacity(size_type additional_objects) const + { return get_next_capacity(this->alloc().max_size(), this->priv_storage(), additional_objects); } + + void deallocate(pointer p, size_type n) + { + if (p && (n > InternalBufferChars)) + this->alloc().deallocate(p, n); + } + + void construct(pointer p, const value_type &value = value_type()) + { new((void*)containers_detail::get_pointer(p)) value_type(value); } + + void destroy(pointer p, size_type n) + { + for(; n--; ++p) + containers_detail::get_pointer(p)->~value_type(); + } + + void destroy(pointer p) + { containers_detail::get_pointer(p)->~value_type(); } + + void allocate_initial_block(size_type n) + { + if (n <= this->max_size()) { + if(n > InternalBufferChars){ + size_type new_cap = this->next_capacity(n); + pointer p = this->allocation_command(allocate_new, n, new_cap, new_cap).first; + this->is_short(false); + this->priv_long_addr(p); + this->priv_size(0); + this->priv_storage(new_cap); + } + } + else + throw_length_error(); + } + + void deallocate_block() + { this->deallocate(this->priv_addr(), this->priv_storage()); } + + size_type max_size() const + { return this->alloc().max_size() - 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]); } + + 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; } + + void priv_long_addr(pointer addr) + { this->members_.m_repr.long_repr().start = addr; } + + size_type priv_storage() const + { return this->is_short() ? priv_short_storage() : priv_long_storage(); } + + size_type priv_short_storage() const + { return InternalBufferChars; } + + size_type priv_long_storage() const + { return this->members_.m_repr.long_repr().storage; } + + void priv_storage(size_type storage) + { + if(!this->is_short()) + this->priv_long_storage(storage); + } + + void priv_long_storage(size_type storage) + { + this->members_.m_repr.long_repr().storage = storage; + } + + size_type priv_size() const + { return this->is_short() ? priv_short_size() : priv_long_size(); } + + size_type priv_short_size() const + { return this->members_.m_repr.short_repr().h.length; } + + size_type priv_long_size() const + { return this->members_.m_repr.long_repr().length; } + + void priv_size(size_type sz) + { + if(this->is_short()) + this->priv_short_size(sz); + else + this->priv_long_size(sz); + } + + void priv_short_size(size_type sz) + { + this->members_.m_repr.s.h.length = (unsigned char)sz; + } + + void priv_long_size(size_type sz) + { + this->members_.m_repr.long_repr().length = static_cast(sz); + } + + void swap(basic_string_base& other) + { + if(this->is_short()){ + if(other.is_short()){ + 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; + } + } + 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; + } + else{ + std::swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr()); + } + } + + allocator_type & this_al = this->alloc(), &other_al = other.alloc(); + if(this_al != other_al){ + containers_detail::do_swap(this_al, other_al); + } + } +}; + +} //namespace containers_detail { + +/// @endcond + +//! The basic_string class represents a Sequence of characters. It contains all the +//! usual operations of a Sequence, and, additionally, it contains standard string +//! operations such as search and concatenation. +//! +//! The basic_string class is parameterized by character type, and by that type's +//! Character Traits. +//! +//! This class has performance characteristics very much like vector<>, meaning, +//! for example, that it does not perform reference-count or copy-on-write, and that +//! concatenation of two strings is an O(N) operation. +//! +//! Some of basic_string's member functions use an unusual method of specifying positions +//! and ranges. In addition to the conventional method using iterators, many of +//! basic_string's member functions use a single value pos of type size_type to represent a +//! position (in which case the position is begin() + pos, and many of basic_string's +//! member functions use two values, pos and n, to represent a range. In that case pos is +//! the beginning of the range and n is its size. That is, the range is +//! [begin() + pos, begin() + pos + n). +//! +//! Note that the C++ standard does not specify the complexity of basic_string operations. +//! In this implementation, basic_string has performance characteristics very similar to +//! those of vector: access to a single character is O(1), while copy and concatenation +//! are O(N). +//! +//! In this implementation, begin(), +//! end(), rbegin(), rend(), operator[], c_str(), and data() do not invalidate iterators. +//! In this implementation, iterators are only invalidated by member functions that +//! explicitly change the string's contents. +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template , class A = std::allocator > +#else +template +#endif +class basic_string + : private containers_detail::basic_string_base +{ + /// @cond + private: + BOOST_COPYABLE_AND_MOVABLE(basic_string) + typedef containers_detail::basic_string_base 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. + + template + struct Eq_traits + : public std::binary_function + { + bool operator()(const typename Tr::char_type& x, + const typename Tr::char_type& y) const + { return Tr::eq(x, y); } + }; + + template + struct Not_within_traits + : public std::unary_function + { + typedef const typename Tr::char_type* Pointer; + const Pointer m_first; + const Pointer m_last; + + Not_within_traits(Pointer f, Pointer l) + : m_first(f), m_last(l) {} + + bool operator()(const typename Tr::char_type& x) const + { + return std::find_if(m_first, m_last, + std::bind1st(Eq_traits(), x)) == m_last; + } + }; + /// @endcond + + 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 A::pointer pointer; + //! Const pointer to CharT + typedef typename A::const_pointer const_pointer; + //! Reference to CharT + typedef typename A::reference reference; + //! Const reference to CharT + typedef typename A::const_reference const_reference; + //! An unsigned integral type + typedef typename A::size_type size_type; + //! A signed integral type + typedef typename A::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 reverse_iterator; + //! Const iterator used to iterate backwards through a string + typedef std::reverse_iterator const_reverse_iterator; + //! The largest possible value of type size_type. That is, size_type(-1). + static const size_type npos; + + /// @cond + private: + typedef constant_iterator 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 + + public: // Constructor, destructor, assignment. + /// @cond + struct reserve_t {}; + + basic_string(reserve_t, size_type n, + const allocator_type& a = allocator_type()) + : base_t(a, n + 1) + { this->priv_terminate_string(); } + + /// @endcond + + //! Effects: Constructs a basic_string taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + explicit basic_string(const allocator_type& a = allocator_type()) + : base_t(a, InternalBufferChars) + { this->priv_terminate_string(); } + + //! Effects: Copy constructs a basic_string. + //! + //! Postcondition: x == *this. + //! + //! Throws: If allocator_type's default constructor or copy constructor throws. + basic_string(const basic_string& s) + : base_t(s.alloc()) + { this->priv_range_initialize(s.begin(), s.end()); } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + basic_string(BOOST_RV_REF(basic_string) s) + : base_t(boost::move((base_t&)s)) + {} + + //! Effects: 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()) + : base_t(a) + { + if (pos > s.size()) + this->throw_out_of_range(); + else + this->priv_range_initialize + (s.begin() + pos, s.begin() + pos + containers_detail::min_value(n, s.size() - pos)); + } + + //! Effects: 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()) + : base_t(a) + { this->priv_range_initialize(s, s + n); } + + //! Effects: 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()) + : base_t(a) + { this->priv_range_initialize(s, s + Traits::length(s)); } + + //! Effects: 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()) + : base_t(a) + { + this->priv_range_initialize(cvalue_iterator(c, n), + cvalue_iterator()); + } + + //! Effects: Constructs a basic_string taking the allocator as parameter, + //! and a range of iterators. + template + basic_string(InputIterator f, InputIterator l, + const allocator_type& a = allocator_type()) + : base_t(a) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_initialize_dispatch(f, l, Result()); + } + + //! Effects: Destroys the basic_string. All used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + ~basic_string() + {} + + //! Effects: Copy constructs a string. + //! + //! Postcondition: x == *this. + //! + //! Complexity: Linear to the elements x contains. + basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) s) + { + if (&s != this) + this->assign(s.begin(), s.end()); + return *this; + } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + basic_string& operator=(BOOST_RV_REF(basic_string) ms) + { + basic_string &s = ms; + if (&s != this){ + this->swap(s); + } + return *this; + } + + //! Effects: Assignment from a null-terminated c-string. + basic_string& operator=(const CharT* s) + { return this->assign(s, s + Traits::length(s)); } + + //! Effects: Assignment from character. + basic_string& operator=(CharT c) + { return this->assign(static_cast(1), c); } + + //! Effects: Returns an iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return this->priv_addr(); } + + //! Effects: Returns a const_iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return this->priv_addr(); } + + //! Effects: Returns a const_iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return this->priv_addr(); } + + + //! Effects: Returns an iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return this->priv_addr() + this->priv_size(); } + + //! Effects: Returns a const_iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return this->priv_addr() + this->priv_size(); } + + //! Effects: Returns a const_iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return this->priv_addr() + this->priv_size(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return reverse_iterator(this->priv_addr() + this->priv_size()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return this->crbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const + { return const_reverse_iterator(this->priv_addr() + this->priv_size()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return reverse_iterator(this->priv_addr()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return this->crend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return const_reverse_iterator(this->priv_addr()); } + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return this->alloc(); } + + //! Effects: Returns the number of the elements contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return this->priv_size(); } + + //! Effects: Returns the number of the elements contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type length() const + { return this->size(); } + + //! Effects: Returns the largest possible size of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return base_t::max_size(); } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type n, CharT c) + { + if (n <= size()) + this->erase(this->begin() + n, this->end()); + else + this->append(n - this->size(), c); + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default constructed. + //! + //! Throws: If memory allocation throws + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type n) + { resize(n, this->priv_null()); } + + //! Effects: 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. + //! + //! Throws: If memory allocation allocation throws + void reserve(size_type res_arg) + { + if (res_arg > this->max_size()) + this->throw_length_error(); + + if (this->capacity() < res_arg){ + size_type n = containers_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); + } + } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return this->priv_capacity(); } + + //! Effects: Erases all the elements of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: 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); + } + } + + //! Effects: Tries to deallocate the excess of memory created + //! with previous allocations. The size of the string is unchanged + //! + //! Throws: Nothing + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { + //Check if shrinking is possible + if(this->priv_storage() > InternalBufferChars){ + //Check if we should pass from dynamically allocated buffer + //to the internal storage + if(this->priv_size() < (InternalBufferChars)){ + //Dynamically allocated buffer attributes + pointer long_addr = this->priv_long_addr(); + size_type long_storage = this->priv_long_storage(); + size_type long_size = this->priv_long_size(); + //Shrink from allocated buffer to the internal one, including trailing null + Traits::copy( containers_detail::get_pointer(this->priv_short_addr()) + , containers_detail::get_pointer(long_addr) + , long_size+1); + this->is_short(true); + this->alloc().deallocate(long_addr, long_storage); + } + else{ + //Shrinking in dynamic buffer + this->priv_shrink_to_fit_dynamic_buffer(alloc_version()); + } + } + } + + //! Effects: Returns true if the vector contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return !this->priv_size(); } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference operator[](size_type n) + { return *(this->priv_addr() + n); } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference operator[](size_type n) const + { return *(this->priv_addr() + n); } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + reference at(size_type n) { + if (n >= size()) + this->throw_out_of_range(); + return *(this->priv_addr() + n); + } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + const_reference at(size_type n) const { + if (n >= size()) + this->throw_out_of_range(); + return *(this->priv_addr() + n); + } + + //! Effects: Calls append(str.data, str.size()). + //! + //! Returns: *this + basic_string& operator+=(const basic_string& s) + { return this->append(s); } + + //! Effects: Calls append(s). + //! + //! Returns: *this + basic_string& operator+=(const CharT* s) + { return this->append(s); } + + //! Effects: Calls append(1, c). + //! + //! Returns: *this + basic_string& operator+=(CharT c) + { this->push_back(c); return *this; } + + //! Effects: Calls append(str.data(), str.size()). + //! + //! Returns: *this + basic_string& append(const basic_string& s) + { return this->append(s.begin(), s.end()); } + + //! Requires: pos <= str.size() + //! + //! Effects: Determines the effective length rlen of the string to append + //! as the smaller of n and str.size() - pos and calls append(str.data() + pos, rlen). + //! + //! Throws: If memory allocation throws and out_of_range if pos > str.size() + //! + //! Returns: *this + basic_string& append(const basic_string& s, size_type pos, size_type n) + { + if (pos > s.size()) + this->throw_out_of_range(); + return this->append(s.begin() + pos, + s.begin() + pos + containers_detail::min_value(n, s.size() - pos)); + } + + //! Requires: s points to an array of at least n elements of CharT. + //! + //! Effects: The function replaces the string controlled by *this with + //! a string of length size() + n whose irst size() elements are a copy of the + //! original string controlled by *this and whose remaining + //! elements are a copy of the initial n elements of s. + //! + //! Throws: If memory allocation throws length_error if size() + n > max_size(). + //! + //! Returns: *this + basic_string& append(const CharT* s, size_type n) + { return this->append(s, s + n); } + + //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. + //! + //! Effects: Calls append(s, traits::length(s)). + //! + //! Returns: *this + basic_string& append(const CharT* s) + { return this->append(s, s + Traits::length(s)); } + + //! Effects: Equivalent to append(basic_string(n, c)). + //! + //! Returns: *this + basic_string& append(size_type n, CharT c) + { return this->append(cvalue_iterator(c, n), cvalue_iterator()); } + + //! Requires: [first,last) is a valid range. + //! + //! Effects: Equivalent to append(basic_string(first, last)). + //! + //! Returns: *this + template + basic_string& append(InputIter first, InputIter last) + { this->insert(this->end(), first, last); return *this; } + + //! Effects: Equivalent to append(static_cast(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); + } + else{ + //No enough memory, insert a new object at the end + this->append((size_type)1, c); + } + } + + //! Effects: Equivalent to assign(str, 0, npos). + //! + //! Returns: *this + basic_string& assign(const basic_string& s) + { return this->operator=(s); } + + //! Effects: The function replaces the string controlled by *this + //! with a string of length str.size() whose elements are a copy of the string + //! controlled by str. Leaves str in a valid but unspecified state. + //! + //! Throws: Nothing + //! + //! Returns: *this + basic_string& assign(BOOST_RV_REF(basic_string) ms) + { return this->swap(ms), *this; } + + //! Requires: pos <= str.size() + //! + //! Effects: Determines the effective length rlen of the string to assign as + //! the smaller of n and str.size() - pos and calls assign(str.data() + pos rlen). + //! + //! Throws: If memory allocation throws or out_of_range if pos > str.size(). + //! + //! Returns: *this + basic_string& assign(const basic_string& s, + size_type pos, size_type n) { + if (pos > s.size()) + this->throw_out_of_range(); + return this->assign(s.begin() + pos, + s.begin() + pos + containers_detail::min_value(n, s.size() - pos)); + } + + //! Requires: s points to an array of at least n elements of CharT. + //! + //! Effects: Replaces the string controlled by *this with a string of + //! length n whose elements are a copy of those pointed to by s. + //! + //! Throws: If memory allocation throws or length_error if n > max_size(). + //! + //! Returns: *this + basic_string& assign(const CharT* s, size_type n) + { return this->assign(s, s + n); } + + //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. + //! + //! Effects: Calls assign(s, traits::length(s)). + //! + //! Returns: *this + basic_string& assign(const CharT* s) + { return this->assign(s, s + Traits::length(s)); } + + //! Effects: Equivalent to assign(basic_string(n, c)). + //! + //! Returns: *this + basic_string& assign(size_type n, CharT c) + { return this->assign(cvalue_iterator(c, n), cvalue_iterator()); } + + //! Effects: Equivalent to assign(basic_string(first, last)). + //! + //! Returns: *this + template + basic_string& assign(InputIter first, InputIter last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + return this->priv_assign_dispatch(first, last, Result()); + } + + //! Requires: pos <= size(). + //! + //! Effects: Calls insert(pos, str.data(), str.size()). + //! + //! Throws: If memory allocation throws or out_of_range if pos > size(). + //! + //! Returns: *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(); + this->insert(this->priv_addr() + pos, s.begin(), s.end()); + return *this; + } + + //! Requires: pos1 <= size() and pos2 <= str.size() + //! + //! Effects: Determines the effective length rlen of the string to insert as + //! the smaller of n and str.size() - pos2 and calls insert(pos1, str.data() + pos2, rlen). + //! + //! Throws: If memory allocation throws or out_of_range if pos1 > size() or pos2 > str.size(). + //! + //! Returns: *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 = containers_detail::min_value(n, s.size() - pos2); + if (this->size() > this->max_size() - len) + this->throw_length_error(); + const CharT *beg_ptr = containers_detail::get_pointer(s.begin()) + pos2; + const CharT *end_ptr = beg_ptr + len; + this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr); + return *this; + } + + //! Requires: s points to an array of at least n elements of CharT and pos <= size(). + //! + //! Effects: Replaces the string controlled by *this with a string of length size() + n + //! whose first pos elements are a copy of the initial elements of the original string + //! controlled by *this and whose next n elements are a copy of the elements in s and whose + //! remaining elements are a copy of the remaining elements of the original string controlled by *this. + //! + //! Throws: If memory allocation throws, out_of_range if pos > size() or + //! length_error if size() + n > max_size(). + //! + //! Returns: *this + basic_string& insert(size_type pos, const CharT* s, size_type n) + { + if (pos > this->size()) + this->throw_out_of_range(); + if (this->size() > this->max_size() - n) + this->throw_length_error(); + this->insert(this->priv_addr() + pos, s, s + n); + return *this; + } + + //! Requires: pos <= size() and s points to an array of at least traits::length(s) + 1 elements of CharT + //! + //! Effects: Calls insert(pos, s, traits::length(s)). + //! + //! Throws: If memory allocation throws, out_of_range if pos > size() + //! length_error if size() > max_size() - Traits::length(s) + //! + //! Returns: *this + basic_string& insert(size_type pos, const CharT* s) + { + if (pos > size()) + this->throw_out_of_range(); + size_type len = Traits::length(s); + if (this->size() > this->max_size() - len) + this->throw_length_error(); + this->insert(this->priv_addr() + pos, s, s + len); + return *this; + } + + //! Effects: Equivalent to insert(pos, basic_string(n, c)). + //! + //! Throws: If memory allocation throws, out_of_range if pos > size() + //! length_error if size() > max_size() - n + //! + //! Returns: *this + basic_string& insert(size_type pos, size_type n, CharT c) + { + if (pos > this->size()) + this->throw_out_of_range(); + if (this->size() > this->max_size() - n) + this->throw_length_error(); + this->insert(const_iterator(this->priv_addr() + pos), n, c); + return *this; + } + + //! Requires: p is a valid iterator on *this. + //! + //! Effects: inserts a copy of c before the character referred to by p. + //! + //! Returns: 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; + this->insert(p, cvalue_iterator(c, 1), cvalue_iterator()); + return this->priv_addr() + new_offset; + } + + + //! Requires: p is a valid iterator on *this. + //! + //! Effects: Inserts n copies of c before the character referred to by p. + //! + //! Returns: 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()); + } + + //! Requires: p is a valid iterator on *this. [first,last) is a valid range. + //! + //! Effects: Equivalent to insert(p - begin(), basic_string(first, last)). + //! + //! Returns: An iterator which refers to the copy of the first + //! inserted character, or p if first == last. + template + void insert(const_iterator p, InputIter first, InputIter last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_insert_dispatch(p, first, last, Result()); + } + + //! Requires: pos <= size() + //! + //! Effects: Determines the effective length xlen of the string to be removed as the smaller of n and size() - pos. + //! The function then replaces the string controlled by *this with a string of length size() - xlen + //! whose first pos elements are a copy of the initial elements of the original string controlled by *this, + //! and whose remaining elements are a copy of the elements of the original string controlled by *this + //! beginning at position pos + xlen. + //! + //! Throws: out_of_range if pos > size(). + //! + //! Returns: *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 + containers_detail::min_value(n, size() - pos)); + return *this; + } + + //! Effects: Removes the character referred to by p. + //! + //! Throws: Nothing + //! + //! Returns: 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) + { + // The move includes the terminating null. + CharT *ptr = const_cast(containers_detail::get_pointer(p)); + Traits::move(ptr, + containers_detail::get_pointer(p + 1), + this->priv_size() - (p - this->priv_addr())); + this->priv_size(this->priv_size()-1); + return iterator(ptr); + } + + //! Requires: first and last are valid iterators on *this, defining a range [first,last). + //! + //! Effects: Removes the characters in the range [first,last). + //! + //! Throws: Nothing + //! + //! Returns: 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) + { + CharT * f = const_cast(containers_detail::get_pointer(first)); + if (first != last) { // The move includes the terminating null. + size_type num_erased = last - first; + Traits::move(f, + containers_detail::get_pointer(last), + (this->priv_size() + 1)-(last - this->priv_addr())); + size_type new_length = this->priv_size() - num_erased; + this->priv_size(new_length); + } + return iterator(f); + } + + //! Requires: !empty() + //! + //! Throws: Nothing + //! + //! Effects: Equivalent to erase(size() - 1, 1). + void pop_back() + { + Traits::assign(this->priv_addr()[this->priv_size()-1], this->priv_null()); + this->priv_size(this->priv_size()-1);; + } + + //! Requires: pos1 <= size(). + //! + //! Effects: Calls replace(pos1, n1, str.data(), str.size()). + //! + //! Throws: if memory allocation throws or out_of_range if pos1 > size(). + //! + //! Returns: *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 = containers_detail::min_value(n1, 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()); + } + + //! Requires: pos1 <= size() and pos2 <= str.size(). + //! + //! Effects: Determines the effective length rlen of the string to be + //! inserted as the smaller of n2 and str.size() - pos2 and calls + //! replace(pos1, n1, str.data() + pos2, rlen). + //! + //! Throws: if memory allocation throws, out_of_range if pos1 > size() or pos2 > str.size(). + //! + //! Returns: *this + 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 = containers_detail::min_value(n1, size() - pos1); + const size_type len2 = containers_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); + } + + //! Requires: pos1 <= size() and s points to an array of at least n2 elements of CharT. + //! + //! Effects: Determines the effective length xlen of the string to be removed as the + //! smaller of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error. + //! Otherwise, the function replaces the string controlled by *this with a string of + //! length size() - xlen + n2 whose first pos1 elements are a copy of the initial elements + //! of the original string controlled by *this, whose next n2 elements are a copy of the + //! initial n2 elements of s, and whose remaining elements are a copy of the elements of + //! the original string controlled by *this beginning at position pos + xlen. + //! + //! Throws: if memory allocation throws, out_of_range if pos1 > size() or length_error + //! if the length of the resulting string would exceed max_size() + //! + //! Returns: *this + 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 = containers_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, + s, s + n2); + } + + //! Requires: pos1 <= size() and s points to an array of at least n2 elements of CharT. + //! + //! Effects: Determines the effective length xlen of the string to be removed as the smaller + //! of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error. Otherwise, + //! the function replaces the string controlled by *this with a string of length size() - xlen + n2 + //! whose first pos1 elements are a copy of the initial elements of the original string controlled + //! by *this, whose next n2 elements are a copy of the initial n2 elements of s, and whose + //! remaining elements are a copy of the elements of the original string controlled by *this + //! beginning at position pos + xlen. + //! + //! Throws: if memory allocation throws, out_of_range if pos1 > size() or length_error + //! if the length of the resulting string would exceed max_size() + //! + //! Returns: *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 = containers_detail::min_value(n1, 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, + s, s + Traits::length(s)); + } + + //! Requires: pos1 <= size(). + //! + //! Effects: Equivalent to replace(pos1, n1, basic_string(n2, c)). + //! + //! Throws: if memory allocation throws, out_of_range if pos1 > size() or length_error + //! if the length of the resulting string would exceed max_size() + //! + //! Returns: *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 = containers_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); + } + + //! Requires: [begin(),i1) and [i1,i2) are valid ranges. + //! + //! Effects: Calls replace(i1 - begin(), i2 - i1, str). + //! + //! Throws: if memory allocation throws + //! + //! Returns: *this + basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str) + { return this->replace(i1, i2, str.begin(), str.end()); } + + //! Requires: [begin(),i1) and [i1,i2) are valid ranges and + //! s points to an array of at least n elements + //! + //! Effects: Calls replace(i1 - begin(), i2 - i1, s, n). + //! + //! Throws: if memory allocation throws + //! + //! Returns: *this + basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s, size_type n) + { return this->replace(i1, i2, s, s + n); } + + //! Requires: [begin(),i1) and [i1,i2) are valid ranges and s points to an + //! array of at least traits::length(s) + 1 elements of CharT. + //! + //! Effects: Calls replace(i1 - begin(), i2 - i1, s, traits::length(s)). + //! + //! Throws: if memory allocation throws + //! + //! Returns: *this + basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s) + { return this->replace(i1, i2, s, s + Traits::length(s)); } + + //! Requires: [begin(),i1) and [i1,i2) are valid ranges. + //! + //! Effects: Calls replace(i1 - begin(), i2 - i1, basic_string(n, c)). + //! + //! Throws: if memory allocation throws + //! + //! Returns: *this + basic_string& replace(const_iterator i1, const_iterator i2, size_type n, CharT c) + { + const size_type len = static_cast(i2 - i1); + if (len >= n) { + Traits::assign(const_cast(containers_detail::get_pointer(i1)), n, c); + erase(i1 + n, i2); + } + else { + Traits::assign(const_cast(containers_detail::get_pointer(i1)), len, c); + insert(i2, n - len, c); + } + return *this; + } + + //! Requires: [begin(),i1), [i1,i2) and [j1,j2) are valid ranges. + //! + //! Effects: Calls replace(i1 - begin(), i2 - i1, basic_string(j1, j2)). + //! + //! Throws: if memory allocation throws + //! + //! Returns: *this + template + basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + return this->priv_replace_dispatch(i1, i2, j1, j2, Result()); + } + + //! Requires: pos <= size() + //! + //! Effects: Determines the effective length rlen of the string to copy as the + //! smaller of n and size() - pos. s shall designate an array of at least rlen elements. + //! The function then replaces the string designated by s with a string of length rlen + //! whose elements are a copy of the string controlled by *this beginning at position pos. + //! The function does not append a null object to the string designated by s. + //! + //! Throws: if memory allocation throws, out_of_range if pos > size(). + //! + //! Returns: 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 = containers_detail::min_value(n, size() - pos); + Traits::copy(s, containers_detail::get_pointer(this->priv_addr() + pos), len); + return len; + } + + //! Effects: *this contains the same sequence of characters that was in s, + //! s contains the same sequence of characters that was in *this. + //! + //! Throws: Nothing + void swap(basic_string& x) + { base_t::swap(x); } + + //! Requires: The program shall not alter any of the values stored in the character array. + //! + //! Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()]. + //! + //! Complexity: constant time. + const CharT* c_str() const + { return containers_detail::get_pointer(this->priv_addr()); } + + //! Requires: The program shall not alter any of the values stored in the character array. + //! + //! Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()]. + //! + //! Complexity: constant time. + const CharT* data() const + { return containers_detail::get_pointer(this->priv_addr()); } + + //! Effects: 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. + //! + //! Throws: Nothing + //! + //! Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos. + size_type find(const basic_string& s, size_type pos = 0) const + { return find(s.c_str(), pos, s.size()); } + + //! Requires: s points to an array of at least n elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: find(basic_string(s,n),pos). + size_type find(const CharT* s, size_type pos, size_type n) const + { + if (pos + n > size()) + return npos; + else { + pointer finish = this->priv_addr() + this->priv_size(); + const const_iterator result = + std::search(containers_detail::get_pointer(this->priv_addr() + pos), + containers_detail::get_pointer(finish), + s, s + n, Eq_traits()); + return result != finish ? result - begin() : npos; + } + } + + //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: find(basic_string(s), pos). + size_type find(const CharT* s, size_type pos = 0) const + { return find(s, pos, Traits::length(s)); } + + //! Throws: Nothing + //! + //! Returns: find(basic_string(1,c), pos). + size_type find(CharT c, size_type pos = 0) const + { + if (pos >= size()) + return npos; + else { + pointer finish = this->priv_addr() + this->priv_size(); + const const_iterator result = + std::find_if(this->priv_addr() + pos, finish, + std::bind2nd(Eq_traits(), c)); + return result != finish ? result - begin() : npos; + } + } + + //! Effects: Determines the highest position xpos, if possible, such + //! that both of the following conditions obtain: + //! a) xpos <= pos and xpos + str.size() <= size(); + //! b) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str. + //! + //! Throws: Nothing + //! + //! Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos. + size_type rfind(const basic_string& str, size_type pos = npos) const + { return rfind(str.c_str(), pos, str.size()); } + + //! Requires: s points to an array of at least n elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: rfind(basic_string(s, n), pos). + size_type rfind(const CharT* s, size_type pos, size_type n) const + { + const size_type len = size(); + + if (n > len) + return npos; + else if (n == 0) + return containers_detail::min_value(len, pos); + else { + const const_iterator last = begin() + containers_detail::min_value(len - n, pos) + n; + const const_iterator result = find_end(begin(), last, + s, s + n, + Eq_traits()); + return result != last ? result - begin() : npos; + } + } + + //! Requires: pos <= size() and s points to an array of at least + //! traits::length(s) + 1 elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: rfind(basic_string(s), pos). + size_type rfind(const CharT* s, size_type pos = npos) const + { return rfind(s, pos, Traits::length(s)); } + + //! Throws: Nothing + //! + //! Returns: rfind(basic_string(1,c),pos). + size_type rfind(CharT c, size_type pos = npos) const + { + const size_type len = size(); + + if (len < 1) + return npos; + else { + const const_iterator last = begin() + containers_detail::min_value(len - 1, pos) + 1; + const_reverse_iterator rresult = + std::find_if(const_reverse_iterator(last), rend(), + std::bind2nd(Eq_traits(), c)); + return rresult != rend() ? (rresult.base() - 1) - begin() : npos; + } + } + + //! Effects: Determines the lowest position xpos, if possible, such that both of the + //! following conditions obtain: a) pos <= xpos and xpos < size(); + //! b) traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str. + //! + //! Throws: Nothing + //! + //! Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos. + size_type find_first_of(const basic_string& s, size_type pos = 0) const + { return find_first_of(s.c_str(), pos, s.size()); } + + //! Requires: s points to an array of at least n elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: 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()) + 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()); + return result != finish ? result - begin() : npos; + } + } + + //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: find_first_of(basic_string(s), pos). + size_type find_first_of(const CharT* s, size_type pos = 0) const + { return find_first_of(s, pos, Traits::length(s)); } + + //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: find_first_of(basic_string(1,c), pos). + size_type find_first_of(CharT c, size_type pos = 0) const + { return find(c, pos); } + + //! Effects: Determines the highest position xpos, if possible, such that both of + //! the following conditions obtain: a) xpos <= pos and xpos < size(); b) + //! traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str. + //! + //! Throws: Nothing + //! + //! Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos. + size_type find_last_of(const basic_string& str, size_type pos = npos) const + { return find_last_of(str.c_str(), pos, str.size()); } + + //! Requires: s points to an array of at least n elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: 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(); + + if (len < 1) + return npos; + else { + const const_iterator last = this->priv_addr() + containers_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()); + return rresult != rend() ? (rresult.base() - 1) - this->priv_addr() : npos; + } + } + + //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: find_last_of(basic_string(1,c),pos). + size_type find_last_of(const CharT* s, size_type pos = npos) const + { return find_last_of(s, pos, Traits::length(s)); } + + //! Throws: Nothing + //! + //! Returns: find_last_of(basic_string(s), pos). + size_type find_last_of(CharT c, size_type pos = npos) const + { return rfind(c, pos); } + + //! Effects: Determines the lowest position xpos, if possible, such that + //! both of the following conditions obtain: + //! a) pos <= xpos and xpos < size(); b) traits::eq(at(xpos), str.at(I)) for no + //! element I of the string controlled by str. + //! + //! Throws: Nothing + //! + //! Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos. + size_type find_first_not_of(const basic_string& str, size_type pos = 0) const + { return find_first_not_of(str.c_str(), pos, str.size()); } + + //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: 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()) + 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(s, s + n)); + return result != finish ? result - this->priv_addr() : npos; + } + } + + //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: find_first_not_of(basic_string(s), pos). + size_type find_first_not_of(const CharT* s, size_type pos = 0) const + { return find_first_not_of(s, pos, Traits::length(s)); } + + //! Throws: Nothing + //! + //! Returns: 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()) + return npos; + else { + pointer finish = this->priv_addr() + this->priv_size(); + const_iterator result + = std::find_if(this->priv_addr() + pos, finish, + std::not1(std::bind2nd(Eq_traits(), c))); + return result != finish ? result - begin() : npos; + } + } + + //! Effects: Determines the highest position xpos, if possible, such that + //! both of the following conditions obtain: a) xpos <= pos and xpos < size(); + //! b) traits::eq(at(xpos), str.at(I)) for no element I of the string controlled by str. + //! + //! Throws: Nothing + //! + //! Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos. + size_type find_last_not_of(const basic_string& str, size_type pos = npos) const + { return find_last_not_of(str.c_str(), pos, str.size()); } + + //! Requires: s points to an array of at least n elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: 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(); + + if (len < 1) + return npos; + else { + const const_iterator last = begin() + containers_detail::min_value(len - 1, pos) + 1; + const const_reverse_iterator rresult = + std::find_if(const_reverse_iterator(last), rend(), + Not_within_traits(s, s + n)); + return rresult != rend() ? (rresult.base() - 1) - begin() : npos; + } + } + + //! Requires: s points to an array of at least traits::length(s) + 1 elements of CharT. + //! + //! Throws: Nothing + //! + //! Returns: find_last_not_of(basic_string(s), pos). + size_type find_last_not_of(const CharT* s, size_type pos = npos) const + { return find_last_not_of(s, pos, Traits::length(s)); } + + //! Throws: Nothing + //! + //! Returns: 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(); + + if (len < 1) + return npos; + else { + const const_iterator last = begin() + containers_detail::min_value(len - 1, pos) + 1; + const_reverse_iterator rresult = + std::find_if(const_reverse_iterator(last), rend(), + std::not1(std::bind2nd(Eq_traits(), c))); + return rresult != rend() ? (rresult.base() - 1) - begin() : npos; + } + } + + //! Requires: Requires: pos <= size() + //! + //! Effects: Determines the effective length rlen of the string to copy as + //! the smaller of n and size() - pos. + //! + //! Throws: If memory allocation throws or out_of_range if pos > size(). + //! + //! Returns: basic_string(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 + containers_detail::min_value(n, size() - pos), this->alloc()); + } + + //! Effects: Determines the effective length rlen of the string to copy as + //! the smaller of size() and str.size(). The function then compares the two strings by + //! calling traits::compare(data(), str.data(), rlen). + //! + //! Throws: Nothing + //! + //! Returns: The nonzero result if the result of the comparison is nonzero. + //! Otherwise, returns a value < 0 if size() < str.size(), a 0 value if size() == str.size(), + //! and value > 0 if size() > str.size() + int compare(const basic_string& str) const + { return s_compare(this->priv_addr(), this->priv_addr() + this->priv_size(), str.priv_addr(), str.priv_addr() + str.priv_size()); } + + //! Requires: pos1 <= size() + //! + //! Effects: Determines the effective length rlen of the string to copy as + //! the smaller of + //! + //! Throws: out_of_range if pos1 > size() + //! + //! Returns: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 + containers_detail::min_value(n1, size() - pos1), + str.priv_addr(), str.priv_addr() + str.priv_size()); + } + + //! Requires: pos1 <= size() and pos2 <= str.size() + //! + //! Effects: Determines the effective length rlen of the string to copy as + //! the smaller of + //! + //! Throws: out_of_range if pos1 > size() or pos2 > str.size() + //! + //! Returns: 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 + containers_detail::min_value(n1, size() - pos1), + str.priv_addr() + pos2, + str.priv_addr() + pos2 + containers_detail::min_value(n2, size() - pos2)); + } + + //! Throws: Nothing + //! + //! Returns: 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)); } + + + //! Requires: pos1 > size() and s points to an array of at least n2 elements of CharT. + //! + //! Throws: out_of_range if pos1 > size() + //! + //! Returns: basic_string(*this, pos, n1).compare(basic_string(s, n2)). + int compare(size_type pos1, size_type n1, + const CharT* s, size_type n2 = npos) const + { + if (pos1 > size()) + this->throw_out_of_range(); + return s_compare(this->priv_addr() + pos1, + this->priv_addr() + pos1 + containers_detail::min_value(n1, size() - pos1), + s, s + n2); + } + + //! Requires: pos1 > size() and s points to an array of at least traits::length(s) + 1 elements of CharT. + //! + //! Throws: out_of_range if pos1 > size() + //! + //! Returns: basic_string(*this, pos, n1).compare(basic_string(s, n2)). + int compare(size_type pos1, size_type n1, const CharT* s) const + { return this->compare(pos1, n1, s, Traits::length(s)); } + + /// @cond + private: + static int s_compare(const_pointer f1, const_pointer l1, + const_pointer f2, const_pointer l2) + { + const difference_type n1 = l1 - f1; + const difference_type n2 = l2 - f2; + const int cmp = Traits::compare(containers_detail::get_pointer(f1), + containers_detail::get_pointer(f2), + containers_detail::min_value(n1, n2)); + return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0)); + } + + void priv_shrink_to_fit_dynamic_buffer(allocator_v1) + { + //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(); + //We can make this nothrow as chars are always NoThrowCopyables + try{ + std::pair ret = this->allocation_command + (allocate_new, long_size+1, long_size+1, real_cap, long_addr); + //Copy and update + Traits::copy( containers_detail::get_pointer(ret.first) + , containers_detail::get_pointer(this->priv_long_addr()) + , long_size+1); + this->priv_long_addr(ret.first); + this->priv_storage(real_cap); + //And release old buffer + this->alloc().deallocate(long_addr, long_storage); + } + catch(...){ + return; + } + } + + void priv_shrink_to_fit_dynamic_buffer(allocator_v2) + { + size_type received_size; + if(this->alloc().allocation_command + ( shrink_in_place | nothrow_allocation + , this->priv_long_storage(), this->priv_long_size()+1 + , received_size, this->priv_long_addr()).first){ + this->priv_storage(received_size); + } + } + + void priv_construct_null(pointer p) + { this->construct(p, 0); } + + static CharT priv_null() + { return (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 + 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 + void priv_range_initialize(ForwardIter f, ForwardIter l, + std::forward_iterator_tag) + { + difference_type n = std::distance(f, l); + this->allocate_initial_block(containers_detail::max_value(n+1, InternalBufferChars)); + priv_uninitialized_copy(f, l, this->priv_addr()); + this->priv_size(n); + this->priv_terminate_string(); + } + + template + void priv_range_initialize(InputIter f, InputIter l) + { + typedef typename std::iterator_traits::iterator_category Category; + this->priv_range_initialize(f, l, Category()); + } + + template + void priv_initialize_dispatch(Integer n, Integer x, containers_detail::true_) + { + this->allocate_initial_block(containers_detail::max_value(n+1, InternalBufferChars)); + priv_uninitialized_fill_n(this->priv_addr(), n, x); + this->priv_size(n); + this->priv_terminate_string(); + } + + template + void priv_initialize_dispatch(InputIter f, InputIter l, containers_detail::false_) + { this->priv_range_initialize(f, l); } + + template inline + void priv_uninitialized_fill_n(FwdIt first, Count count, const CharT val) + { + //Save initial position + FwdIt init = first; + + BOOST_TRY{ + //Construct objects + for (; count--; ++first){ + this->construct(first, val); + } + } + BOOST_CATCH(...){ + //Call destructors + for (; init != first; ++init){ + this->destroy(init); + } + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template inline + size_type priv_uninitialized_copy(InpIt first, InpIt last, FwdIt dest) + { + //Save initial destination position + FwdIt dest_init = dest; + size_type constructed = 0; + + BOOST_TRY{ + //Try to build objects + for (; first != last; ++dest, ++first, ++constructed){ + this->construct(dest, *first); + } + } + BOOST_CATCH(...){ + //Call destructors + for (; constructed--; ++dest_init){ + this->destroy(dest_init); + } + BOOST_RETHROW + } + BOOST_CATCH_END + return (constructed); + } + + template + basic_string& priv_assign_dispatch(Integer n, Integer x, containers_detail::true_) + { return this->assign((size_type) n, (CharT) x); } + + template + basic_string& priv_assign_dispatch(InputIter f, InputIter l, + containers_detail::false_) + { + size_type cur = 0; + CharT *ptr = containers_detail::get_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 + 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 + 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 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(containers_detail::get_pointer(position + n)), + containers_detail::get_pointer(position), + (elems_after - n) + 1); + this->priv_copy(first, last, const_cast(containers_detail::get_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(containers_detail::get_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 + value_type *oldbuf = containers_detail::get_pointer(old_start); + value_type *newbuf = containers_detail::get_pointer(new_start); + const value_type *pos = containers_detail::get_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 + void priv_insert_dispatch(const_iterator p, Integer n, Integer x, + containers_detail::true_) + { insert(p, (size_type) n, (CharT) x); } + + template + void priv_insert_dispatch(const_iterator p, InputIter first, InputIter last, + containers_detail::false_) + { + typedef typename std::iterator_traits::iterator_category Category; + priv_insert(p, first, last, Category()); + } + + template + void priv_copy(InputIterator first, InputIterator last, OutIterator result) + { + for ( ; first != last; ++first, ++result) + Traits::assign(*result, *first); + } + + void priv_copy(const CharT* first, const CharT* last, CharT* result) + { Traits::copy(result, first, last - first); } + + template + basic_string& priv_replace_dispatch(const_iterator first, const_iterator last, + Integer n, Integer x, + containers_detail::true_) + { return this->replace(first, last, (size_type) n, (CharT) x); } + + template + basic_string& priv_replace_dispatch(const_iterator first, const_iterator last, + InputIter f, InputIter l, + containers_detail::false_) + { + typedef typename std::iterator_traits::iterator_category Category; + return this->priv_replace(first, last, f, l, Category()); + } + + + template + 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 + 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(containers_detail::get_pointer(first))); + this->erase(first + n, last); + } + else { + ForwardIter m = f; + std::advance(m, len); + this->priv_copy(f, m, const_cast(containers_detail::get_pointer(first))); + this->insert(last, m, l); + } + return *this; + } + /// @endcond +}; + +//!Typedef for a basic_string of +//!narrow characters +typedef basic_string + + ,std::allocator > +string; + +//!Typedef for a basic_string of +//!narrow characters +typedef basic_string + + ,std::allocator > +wstring; + +/// @cond + +template +const typename basic_string::size_type +basic_string::npos + = (typename basic_string::size_type) -1; + +/// @endcond + +// ------------------------------------------------------------ +// Non-member functions. + +// Operator+ + +template +inline basic_string +operator+(const basic_string& x, + const basic_string& y) +{ + typedef basic_string str_t; + typedef typename str_t::reserve_t reserve_t; + reserve_t reserve; + str_t result(reserve, x.size() + y.size(), x.alloc()); + result.append(x); + result.append(y); + return result; +} + +template 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& y) +{ + mx += y; + return boost::move(mx); +} + +template inline +BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) + operator+(const basic_string& x, + BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my) +{ + typedef typename basic_string::size_type size_type; + return my.replace(size_type(0), size_type(0), x); +} + +template +inline basic_string +operator+(const CharT* s, const basic_string& y) +{ + typedef basic_string 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 result; +} + +template 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::size_type size_type; + return boost::move(my.get().replace(size_type(0), size_type(0), s)); +} + +template +inline basic_string +operator+(CharT c, const basic_string& y) +{ + typedef basic_string 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 result; +} + +template 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) +{ + typedef typename basic_string::size_type size_type; + return my.replace(size_type(0), size_type(0), &c, &c + 1); +} + +template +inline basic_string +operator+(const basic_string& x, const CharT* s) +{ + typedef basic_string 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.alloc()); + result.append(x); + result.append(s, s + n); + return result; +} + +template +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) +{ + mx += s; + return boost::move(mx); +} + +template +inline basic_string +operator+(const basic_string& x, const CharT c) +{ + typedef basic_string str_t; + typedef typename str_t::reserve_t reserve_t; + reserve_t reserve; + str_t result(reserve, x.size() + 1, x.alloc()); + result.append(x); + result.push_back(c); + return result; +} + +template +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) +{ + mx += c; + return boost::move(mx); +} + +// Operator== and operator!= + +template +inline bool +operator==(const basic_string& x, + const basic_string& y) +{ + return x.size() == y.size() && + Traits::compare(x.data(), y.data(), x.size()) == 0; +} + +template +inline bool +operator==(const CharT* s, const basic_string& y) +{ + typename basic_string::size_type n = Traits::length(s); + return n == y.size() && Traits::compare(s, y.data(), n) == 0; +} + +template +inline bool +operator==(const basic_string& x, const CharT* s) +{ + typename basic_string::size_type n = Traits::length(s); + return x.size() == n && Traits::compare(x.data(), s, n) == 0; +} + +template +inline bool +operator!=(const basic_string& x, + const basic_string& y) + { return !(x == y); } + +template +inline bool +operator!=(const CharT* s, const basic_string& y) + { return !(s == y); } + +template +inline bool +operator!=(const basic_string& x, const CharT* s) + { return !(x == s); } + + +// Operator< (and also >, <=, and >=). + +template +inline bool +operator<(const basic_string& x, const basic_string& y) +{ + return x.compare(y) < 0; +// return basic_string +// ::s_compare(x.begin(), x.end(), y.begin(), y.end()) < 0; +} + +template +inline bool +operator<(const CharT* s, const basic_string& y) +{ + return y.compare(s) > 0; +// basic_string::size_type n = Traits::length(s); +// return basic_string +// ::s_compare(s, s + n, y.begin(), y.end()) < 0; +} + +template +inline bool +operator<(const basic_string& x, + const CharT* s) +{ + return x.compare(s) < 0; +// basic_string::size_type n = Traits::length(s); +// return basic_string +// ::s_compare(x.begin(), x.end(), s, s + n) < 0; +} + +template +inline bool +operator>(const basic_string& x, + const basic_string& y) { + return y < x; +} + +template +inline bool +operator>(const CharT* s, const basic_string& y) { + return y < s; +} + +template +inline bool +operator>(const basic_string& x, const CharT* s) +{ + return s < x; +} + +template +inline bool +operator<=(const basic_string& x, + const basic_string& y) +{ + return !(y < x); +} + +template +inline bool +operator<=(const CharT* s, const basic_string& y) + { return !(y < s); } + +template +inline bool +operator<=(const basic_string& x, const CharT* s) + { return !(s < x); } + +template +inline bool +operator>=(const basic_string& x, + const basic_string& y) + { return !(x < y); } + +template +inline bool +operator>=(const CharT* s, const basic_string& y) + { return !(s < y); } + +template +inline bool +operator>=(const basic_string& x, const CharT* s) + { return !(x < s); } + +// Swap. +template +inline void swap(basic_string& x, basic_string& y) +{ x.swap(y); } + +/// @cond +// I/O. +namespace containers_detail { + +template +inline bool +string_fill(std::basic_ostream& os, + std::basic_streambuf* buf, + std::size_t n) +{ + CharT f = os.fill(); + std::size_t i; + bool ok = true; + + for (i = 0; i < n; i++) + ok = ok && !Traits::eq_int_type(buf->sputc(f), Traits::eof()); + return ok; +} + +} //namespace containers_detail { +/// @endcond + +template +std::basic_ostream& +operator<<(std::basic_ostream& os, const basic_string& s) +{ + typename std::basic_ostream::sentry sentry(os); + bool ok = false; + + if (sentry) { + ok = true; + typename basic_string::size_type n = s.size(); + typename basic_string::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* buf = os.rdbuf(); + + if (w != 0 && n < w) + pad_len = w - n; + + if (!left) + ok = containers_detail::string_fill(os, buf, pad_len); + + ok = ok && + buf->sputn(s.data(), std::streamsize(n)) == std::streamsize(n); + + if (left) + ok = ok && containers_detail::string_fill(os, buf, pad_len); + } + + if (!ok) + os.setstate(std::ios_base::failbit); + + return os; +} + + +template +std::basic_istream& +operator>>(std::basic_istream& is, basic_string& s) +{ + typename std::basic_istream::sentry sentry(is); + + if (sentry) { + std::basic_streambuf* buf = is.rdbuf(); + const std::ctype& ctype = std::use_facet >(is.getloc()); + + s.clear(); + std::size_t n = is.width(0); + if (n == 0) + n = static_cast(-1); + else + s.reserve(n); + + while (n-- > 0) { + typename Traits::int_type c1 = buf->sbumpc(); + + if (Traits::eq_int_type(c1, Traits::eof())) { + is.setstate(std::ios_base::eofbit); + break; + } + else { + CharT c = Traits::to_char_type(c1); + + if (ctype.is(std::ctype::space, c)) { + if (Traits::eq_int_type(buf->sputbackc(c), Traits::eof())) + is.setstate(std::ios_base::failbit); + break; + } + else + s.push_back(c); + } + } + + // If we have read no characters, then set failbit. + if (s.size() == 0) + is.setstate(std::ios_base::failbit); + } + else + is.setstate(std::ios_base::failbit); + + return is; +} + +template +std::basic_istream& +getline(std::istream& is, basic_string& s,CharT delim) +{ + typename basic_string::size_type nread = 0; + typename std::basic_istream::sentry sentry(is, true); + if (sentry) { + std::basic_streambuf* buf = is.rdbuf(); + s.clear(); + + while (nread < s.max_size()) { + int c1 = buf->sbumpc(); + if (Traits::eq_int_type(c1, Traits::eof())) { + is.setstate(std::ios_base::eofbit); + break; + } + else { + ++nread; + CharT c = Traits::to_char_type(c1); + if (!Traits::eq(c, delim)) + s.push_back(c); + else + break; // Character is extracted but not appended. + } + } + } + if (nread == 0 || nread >= s.max_size()) + is.setstate(std::ios_base::failbit); + + return is; +} + +template +inline std::basic_istream& +getline(std::basic_istream& is, basic_string& s) +{ + return getline(is, s, '\n'); +} + +template +inline std::size_t hash_value(basic_string, A> const& v) +{ + return hash_range(v.begin(), v.end()); +} + +}} + +/// @cond + +namespace boost { +/* +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value; +}; +*/ +} + +/// @endcond + +#include + +#endif // BOOST_CONTAINERS_STRING_HPP diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp new file mode 100644 index 0000000..22e198a --- /dev/null +++ b/include/boost/container/vector.hpp @@ -0,0 +1,1999 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_CONTAINERS_CONTAINERS_VECTOR_HPP +#define BOOST_CONTAINERS_CONTAINERS_VECTOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace container { + +/// @cond + +namespace containers_detail { + +//! Const vector_iterator used to iterate through a vector. +template +class vector_const_iterator + : public std::iterator::value_type + ,typename std::iterator_traits::difference_type + ,typename boost::pointer_to_other + ::value_type + >::type + ,const typename std::iterator_traits::value_type &> +{ + public: + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename boost::pointer_to_other::type pointer; + typedef const value_type& reference; + + /// @cond + protected: + Pointer m_ptr; + + public: + Pointer get_ptr() const { return m_ptr; } + explicit vector_const_iterator(Pointer ptr) : m_ptr(ptr){} + /// @endcond + + public: + + //Constructors + vector_const_iterator() : m_ptr(0){} + + //Pointer like operators + reference operator*() const + { return *m_ptr; } + + const value_type * operator->() const + { return containers_detail::get_pointer(m_ptr); } + + reference operator[](difference_type off) const + { return m_ptr[off]; } + + //Increment / Decrement + vector_const_iterator& operator++() + { ++m_ptr; return *this; } + + vector_const_iterator operator++(int) + { Pointer tmp = m_ptr; ++*this; return vector_const_iterator(tmp); } + + vector_const_iterator& operator--() + { --m_ptr; return *this; } + + vector_const_iterator operator--(int) + { Pointer tmp = m_ptr; --*this; return vector_const_iterator(tmp); } + + //Arithmetic + vector_const_iterator& operator+=(difference_type off) + { m_ptr += off; return *this; } + + vector_const_iterator operator+(difference_type off) const + { return vector_const_iterator(m_ptr+off); } + + friend vector_const_iterator operator+(difference_type off, const vector_const_iterator& right) + { return vector_const_iterator(off + right.m_ptr); } + + vector_const_iterator& operator-=(difference_type off) + { m_ptr -= off; return *this; } + + vector_const_iterator operator-(difference_type off) const + { return vector_const_iterator(m_ptr-off); } + + difference_type operator-(const vector_const_iterator& right) const + { return m_ptr - right.m_ptr; } + + //Comparison operators + bool operator== (const vector_const_iterator& r) const + { return m_ptr == r.m_ptr; } + + bool operator!= (const vector_const_iterator& r) const + { return m_ptr != r.m_ptr; } + + bool operator< (const vector_const_iterator& r) const + { return m_ptr < r.m_ptr; } + + bool operator<= (const vector_const_iterator& r) const + { return m_ptr <= r.m_ptr; } + + bool operator> (const vector_const_iterator& r) const + { return m_ptr > r.m_ptr; } + + bool operator>= (const vector_const_iterator& r) const + { return m_ptr >= r.m_ptr; } +}; + +//! Iterator used to iterate through a vector +template +class vector_iterator + : public vector_const_iterator +{ + public: + explicit vector_iterator(Pointer ptr) + : vector_const_iterator(ptr) + {} + + public: + typedef typename std::iterator_traits::value_type value_type; + typedef typename vector_const_iterator::difference_type difference_type; + typedef Pointer pointer; + typedef value_type& reference; + + //Constructors + vector_iterator() + {} + + //Pointer like operators + reference operator*() const + { return *this->m_ptr; } + + value_type* operator->() const + { return containers_detail::get_pointer(this->m_ptr); } + + reference operator[](difference_type off) const + { return this->m_ptr[off]; } + + //Increment / Decrement + vector_iterator& operator++() + { ++this->m_ptr; return *this; } + + vector_iterator operator++(int) + { pointer tmp = this->m_ptr; ++*this; return vector_iterator(tmp); } + + vector_iterator& operator--() + { --this->m_ptr; return *this; } + + vector_iterator operator--(int) + { vector_iterator tmp = *this; --*this; return vector_iterator(tmp); } + + // Arithmetic + vector_iterator& operator+=(difference_type off) + { this->m_ptr += off; return *this; } + + vector_iterator operator+(difference_type off) const + { return vector_iterator(this->m_ptr+off); } + + friend vector_iterator operator+(difference_type off, const vector_iterator& right) + { return vector_iterator(off + right.m_ptr); } + + vector_iterator& operator-=(difference_type off) + { this->m_ptr -= off; return *this; } + + vector_iterator operator-(difference_type off) const + { return vector_iterator(this->m_ptr-off); } + + difference_type operator-(const vector_const_iterator& right) const + { return static_cast&>(*this) - right; } +}; + +template +struct vector_value_traits +{ + typedef T value_type; + typedef A allocator_type; + static const bool trivial_dctr = boost::has_trivial_destructor::value; + static const bool trivial_dctr_after_move = trivial_dctr; + //::boost::has_trivial_destructor_after_move::value || trivial_dctr; + static const bool trivial_copy = has_trivial_copy::value; + static const bool nothrow_copy = has_nothrow_copy::value; + static const bool trivial_assign = has_trivial_assign::value; + static const bool nothrow_assign = has_nothrow_assign::value; + + //This is the anti-exception array destructor + //to deallocate values already constructed + typedef typename containers_detail::if_c + + ,containers_detail::scoped_destructor_n + >::type OldArrayDestructor; + //This is the anti-exception array destructor + //to destroy objects created with copy construction + typedef typename containers_detail::if_c + + ,containers_detail::scoped_destructor_n + >::type ArrayDestructor; + //This is the anti-exception array deallocator + typedef typename containers_detail::if_c + + ,containers_detail::scoped_array_deallocator + >::type ArrayDeallocator; +}; + +//!This struct deallocates and allocated memory +template +struct vector_alloc_holder +{ + typedef typename A::pointer pointer; + typedef typename A::size_type size_type; + typedef typename A::value_type value_type; + typedef vector_value_traits value_traits; + + //Constructor, does not throw + vector_alloc_holder(const A &a) + : members_(a) + {} + + //Destructor + ~vector_alloc_holder() + { + this->prot_destroy_all(); + this->prot_deallocate(); + } + + typedef containers_detail::integral_constant allocator_v1; + typedef containers_detail::integral_constant allocator_v2; + typedef containers_detail::integral_constant::value> alloc_version; + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0) + { + return allocation_command(command, limit_size, preferred_size, + received_size, reuse, alloc_version()); + } + + std::pair + 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(0), false); + received_size = preferred_size; + return std::make_pair(this->alloc().allocate(received_size), false); + } + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, + const pointer &reuse, + allocator_v2) + { + return this->alloc().allocation_command + (command, limit_size, preferred_size, received_size, reuse); + } + + size_type next_capacity(size_type additional_objects) const + { return get_next_capacity(this->alloc().max_size(), this->members_.m_capacity, additional_objects); } + + struct members_holder + : public A + { + private: + members_holder(const members_holder&); + + public: + members_holder(const A &alloc) + : A(alloc), m_start(0), m_size(0), m_capacity(0) + {} + + pointer m_start; + size_type m_size; + size_type m_capacity; + } members_; + + A &alloc() + { return members_; } + + const A &alloc() const + { return members_; } + + protected: + void prot_deallocate() + { + 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; + } + + void destroy(value_type* p) + { + if(!value_traits::trivial_dctr) + containers_detail::get_pointer(p)->~value_type(); + } + + void destroy_n(value_type* p, size_type n) + { + if(!value_traits::trivial_dctr) + for(; n--; ++p) p->~value_type(); + } + + void prot_destroy_all() + { + this->destroy_n(containers_detail::get_pointer(this->members_.m_start), this->members_.m_size); + this->members_.m_size = 0; + } +}; + +} //namespace containers_detail { +/// @endcond + +//! \class vector +//! 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 > +#else +template +#endif +class vector : private containers_detail::vector_alloc_holder +{ + /// @cond + typedef vector self_t; + typedef containers_detail::vector_alloc_holder base_t; + /// @endcond + public: + //! The type of object, T, stored in the vector + typedef T value_type; + //! Pointer to T + typedef typename A::pointer pointer; + //! Const pointer to T + typedef typename A::const_pointer const_pointer; + //! Reference to T + typedef typename A::reference reference; + //! Const reference to T + typedef typename A::const_reference const_reference; + //! An unsigned integral type + typedef typename A::size_type size_type; + //! A signed integral type + typedef typename A::difference_type difference_type; + //! The allocator type + typedef A allocator_type; + //! The random access iterator + typedef containers_detail::vector_iterator iterator; + //! The random access const_iterator + typedef containers_detail::vector_const_iterator const_iterator; + + //! Iterator used to iterate backwards through a vector. + typedef std::reverse_iterator + reverse_iterator; + //! Const iterator used to iterate backwards through a vector. + typedef std::reverse_iterator + const_reverse_iterator; + //! The stored allocator type + typedef allocator_type stored_allocator_type; + + /// @cond + private: + BOOST_COPYABLE_AND_MOVABLE(vector) + typedef containers_detail::advanced_insert_aux_int advanced_insert_aux_int_t; + typedef containers_detail::vector_value_traits 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 constant_iterator cvalue_iterator; + typedef repeat_iterator repeat_it; + typedef boost::move_iterator repeat_move_it; + /// @endcond + + public: + + //! Effects: Constructs a vector taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + explicit vector(const A& a = A()) + : base_t(a) + {} + + //! Effects: Constructs a vector that will use a copy of allocator a + //! and inserts n default contructed values. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + explicit vector(size_type n) + : base_t(allocator_type()) + { + //Allocate + size_type real_cap; + std::pair ret = + this->allocation_command(allocate_new, n, n, real_cap, this->members_.m_start); + T *new_mem = containers_detail::get_pointer(ret.first); + //Anti-exception rollback + typename value_traits::ArrayDeallocator scoped_alloc(new_mem, this->alloc(), real_cap); + //Default constructor + containers_detail::default_construct_aux_proxy proxy(n); + proxy.uninitialized_copy_all_to(new_mem); + //All ok, commit + scoped_alloc.release(); + } + + //! Effects: Constructs a vector that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: 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); } + + //! Effects: Copy constructs a vector. + //! + //! Postcondition: x == *this. + //! + //! Complexity: Linear to the elements x contains. + vector(const vector& x) + : base_t(static_cast(x).alloc()) + { *this = x; } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + vector(BOOST_RV_REF(vector) mx) + : base_t(static_cast(mx).alloc()) + { this->swap(mx); } + + //! Effects: Constructs a vector that will use a copy of allocator a + //! and inserts a copy of the range [first, last) in the vector. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's constructor taking an dereferenced InIt throws. + //! + //! Complexity: Linear to the range [first, last). + template + vector(InIt first, InIt last, const allocator_type& a = allocator_type()) + : base_t(a) + { this->assign(first, last); } + + //! Effects: Destroys the vector. All stored values are destroyed + //! and used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements. + ~vector() + {} //vector_alloc_holder clears the data + + //! Effects: Returns an iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return iterator(this->members_.m_start); } + + //! Effects: Returns a const_iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return const_iterator(this->members_.m_start); } + + //! Effects: Returns an iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return iterator(this->members_.m_start + this->members_.m_size); } + + //! Effects: Returns a const_iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return this->cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return reverse_iterator(this->end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin()const + { return this->crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return reverse_iterator(this->begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return this->crend(); } + + //! Effects: Returns a const_iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return const_iterator(this->members_.m_start); } + + //! Effects: Returns a const_iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return const_iterator(this->members_.m_start + this->members_.m_size); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin()const + { return const_reverse_iterator(this->end());} + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return const_reverse_iterator(this->begin()); } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference front() + { return *this->members_.m_start; } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference front() const + { return *this->members_.m_start; } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the last + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference back() + { return this->members_.m_start[this->members_.m_size - 1]; } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the last + //! element of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference back() const + { return this->members_.m_start[this->members_.m_size - 1]; } + + //! Returns: A pointer such that [data(),data() + size()) is a valid range. + //! For a non-empty vector, data() == &front(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + pointer data() + { return this->members_.m_start; } + + //! Returns: A pointer such that [data(),data() + size()) is a valid range. + //! For a non-empty vector, data() == &front(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_pointer data() const + { return this->members_.m_start; } + + //! Effects: Returns the number of the elements contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return this->members_.m_size; } + + //! Effects: Returns the largest possible size of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return this->alloc().max_size(); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return this->members_.m_capacity; } + + //! Effects: Returns true if the vector contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return !this->members_.m_size; } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference operator[](size_type n) + { return this->members_.m_start[n]; } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference operator[](size_type n) const + { return this->members_.m_start[n]; } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + reference at(size_type n) + { this->priv_check_range(n); return this->members_.m_start[n]; } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + const_reference at(size_type n) const + { this->priv_check_range(n); return this->members_.m_start[n]; } + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return this->alloc(); } + + const stored_allocator_type &get_stored_allocator() const + { return this->alloc(); } + + stored_allocator_type &get_stored_allocator() + { return this->alloc(); } + + //! Effects: 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. + //! + //! Throws: 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 ret = + this->allocation_command + (allocate_new | expand_fwd | expand_bwd, + new_cap, 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){ + #ifdef BOOST_CONTAINERS_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(containers_detail::get_pointer(this->members_.m_start)); + containers_detail::advanced_insert_aux_proxy, T*> + proxy(::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it)); + //Backwards (and possibly forward) expansion + if(ret.second){ + #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS + ++this->num_expand_bwd; + #endif + this->priv_range_insert_expand_backwards + ( containers_detail::get_pointer(ret.first) + , real_cap + , containers_detail::get_pointer(this->members_.m_start) + , 0 + , proxy); + } + //New buffer + else{ + #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS + ++this->num_alloc; + #endif + this->priv_range_insert_new_allocation + ( containers_detail::get_pointer(ret.first) + , real_cap + , containers_detail::get_pointer(this->members_.m_start) + , 0 + , proxy); + } + } + } + } + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x) + { + if (&x != this){ + this->assign(x.members_.m_start, x.members_.m_start + x.members_.m_size); + } + return *this; + } + + //! Effects: Move assignment. All mx's values are transferred to *this. + //! + //! Postcondition: x.empty(). *this contains a the elements x had + //! before the function. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Linear. + vector& operator=(BOOST_RV_REF(vector) x) + { + if (&x != this){ + this->swap(x); + x.clear(); + } + return *this; + } + + //! Effects: Assigns the n copies of val to *this. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void assign(size_type n, const value_type& val) + { this->assign(cvalue_iterator(val, n), cvalue_iterator()); } + + //! Effects: Assigns the the range [first, last) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! Complexity: Linear to n. + template + void assign(InIt first, InIt last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_assign_dispatch(first, last, Result()); + } + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Effects: Inserts a copy of x at the end of the vector. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_back(const T &x); + + //! Effects: Constructs a new element in the end of the vector + //! and moves the resources of mx to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + void push_back(T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back) + #endif + +/* + 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(x)); } + + template + typename containers_detail::enable_if_c + ::value && + containers_detail::is_same::value + >::type + push_back(const U &u) + { return priv_push_back(u); } + + #endif + + //! Effects: Constructs a new element in the end of the vector + //! and moves the resources of mx to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + void push_back(BOOST_RV_REF(T) x) + { + if (this->members_.m_size < this->members_.m_capacity){ + //There is more memory, just construct a new object at the end + new((void*)containers_detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(::boost::move(x)); + ++this->members_.m_size; + } + else{ + this->insert(this->cend(), ::boost::move(x)); + } + } +*/ + //! Effects: Constructs a new element in the end of the vector + //! and moves the resources of mx to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + + + #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the end of the vector. + //! + //! Throws: If memory allocation throws or the in-place constructor throws. + //! + //! Complexity: Amortized constant time. + template + void emplace_back(Args &&...args) + { + T* back_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size; + if (this->members_.m_size < this->members_.m_capacity){ + //There is more memory, just construct a new object at the end + new((void*)(back_pos))value_type(::boost::forward(args)...); + ++this->members_.m_size; + } + else{ + typedef containers_detail::advanced_insert_aux_emplace type; + type &&proxy = type(::boost::forward(args)...); + priv_range_insert(back_pos, 1, proxy); + } + } + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... before position + //! + //! Throws: If memory allocation throws or the in-place constructor throws. + //! + //! Complexity: If position is end(), amortized constant time + //! Linear time otherwise. + template + 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 containers_detail::advanced_insert_aux_emplace type; + type &&proxy = type(::boost::forward(args)...); + priv_range_insert(position.get_ptr(), 1, proxy); + return iterator(this->members_.m_start + pos_n); + } + + #else + + void emplace_back() + { + T* back_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size; + if (this->members_.m_size < this->members_.m_capacity){ + //There is more memory, just construct a new object at the end + new((void*)(back_pos))value_type(); + ++this->members_.m_size; + } + else{ + containers_detail::advanced_insert_aux_emplace proxy; + priv_range_insert(back_pos, 1, proxy); + } + } + + iterator emplace(const_iterator position) + { + size_type pos_n = position - cbegin(); + containers_detail::advanced_insert_aux_emplace proxy; + priv_range_insert(containers_detail::get_pointer(position.get_ptr()), 1, proxy); + return iterator(this->members_.m_start + pos_n); + } + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + T* back_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size; \ + if (this->members_.m_size < this->members_.m_capacity){ \ + new((void*)(back_pos))value_type \ + (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + ++this->members_.m_size; \ + } \ + else{ \ + containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ + \ + proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + priv_range_insert(back_pos, 1, proxy); \ + } \ + } \ + \ + template \ + iterator emplace(const_iterator pos, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \ + { \ + size_type pos_n = pos - cbegin(); \ + containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ + \ + proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \ + priv_range_insert(containers_detail::get_pointer(pos.get_ptr()), 1, proxy); \ + return iterator(this->members_.m_start + pos_n); \ + } \ + //! + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) + #include BOOST_PP_LOCAL_ITERATE() + + #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() + //! allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(vector& x) + { + allocator_type &this_al = this->alloc(), &other_al = x.alloc(); + //Just swap internals + containers_detail::do_swap(this->members_.m_start, x.members_.m_start); + containers_detail::do_swap(this->members_.m_size, x.members_.m_size); + containers_detail::do_swap(this->members_.m_capacity, x.members_.m_capacity); + + if (this_al != other_al){ + containers_detail::do_swap(this_al, other_al); + } + } + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Insert a copy of x before position. + //! + //! Throws: If memory allocation throws or x's copy constructor throws. + //! + //! Complexity: If position is end(), amortized constant time + //! Linear time otherwise. + iterator insert(const_iterator position, const T &x); + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Insert a new element before position with mx's resources. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: 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 + + //! Requires: pos must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [first, last) range before pos. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws or T's copy constructor throws. + //! + //! Complexity: Linear to std::distance [first, last). + template + void insert(const_iterator pos, InIt first, InIt last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = containers_detail::is_convertible::value; + typedef containers_detail::bool_ Result; + this->priv_insert_dispatch(pos, first, last, Result()); + } + + //! Requires: pos must be a valid iterator of *this. + //! + //! Effects: Insert n copies of x before pos. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void insert(const_iterator p, size_type n, const T& x) + { this->insert(p, cvalue_iterator(x, n), cvalue_iterator()); } + + //! Effects: Removes the last element from the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + void pop_back() + { + //Destroy last element + --this->members_.m_size; + this->destroy(containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size); + } + + //! Effects: Erases the element at position pos. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements between pos and the + //! last element. Constant if pos is the last element. + iterator erase(const_iterator position) + { + T *pos = containers_detail::get_pointer(position.get_ptr()); + T *beg = containers_detail::get_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(containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size); + return iterator(position.get_ptr()); + } + + //! Effects: Erases the elements pointed by [first, last). + //! + //! Throws: Nothing. + //! + //! Complexity: 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) + { + if (first != last){ // worth doing, copy down over hole + T* end_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size; + T* ptr = containers_detail::get_pointer(boost::move + (containers_detail::get_pointer(last.get_ptr()) + ,end_pos + ,containers_detail::get_pointer(first.get_ptr()) + )); + size_type destroyed = (end_pos - ptr); + this->destroy_n(ptr, destroyed); + this->members_.m_size -= destroyed; + } + return iterator(first.get_ptr()); + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size, const T& x) + { + 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()); + } + else{ + //Insert new elements at the end + this->insert(const_iterator(finish), new_size - this->size(), x); + } + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default constructed. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size) + { + 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); + containers_detail::default_construct_aux_proxy proxy(n); + priv_range_insert(this->cend().get_ptr(), n, proxy); + } + } + + //! Effects: Erases all the elements of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the vector. + void clear() + { this->prot_destroy_all(); } + + //! Effects: Tries to deallocate the excess of memory created + //! with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy/move constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { priv_shrink_to_fit(alloc_version()); } + + /// @cond + + private: + iterator priv_insert(const_iterator position, const T &x) + { + //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); + } + + iterator priv_insert(const_iterator position, BOOST_RV_REF(T) x) + { + //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); + } + + template + void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x) + { + if (this->members_.m_size < this->members_.m_capacity){ + //There is more memory, just construct a new object at the end + new((void*)containers_detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(::boost::forward(x)); + ++this->members_.m_size; + } + else{ + this->insert(this->cend(), ::boost::forward(x)); + } + } + + void priv_shrink_to_fit(allocator_v1) + { + if(this->members_.m_capacity){ + if(!size()){ + this->prot_deallocate(); + } + else{ + //Allocate a new buffer. + size_type real_cap = 0; + std::pair 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(containers_detail::get_pointer(this->members_.m_start)); + containers_detail::advanced_insert_aux_proxy, T*> + proxy(::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it)); + #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS + ++this->num_alloc; + #endif + this->priv_range_insert_new_allocation + ( containers_detail::get_pointer(ret.first) + , real_cap + , containers_detail::get_pointer(this->members_.m_start) + , 0 + , proxy); + } + else{ + this->alloc().deallocate(ret.first, real_cap); + } + } + } + } + + void priv_shrink_to_fit(allocator_v2) + { + if(this->members_.m_capacity){ + if(!size()){ + this->prot_deallocate(); + } + else{ + size_type received_size; + if(this->alloc().allocation_command + ( shrink_in_place | nothrow_allocation + , this->capacity(), this->size() + , received_size, this->members_.m_start).first){ + this->members_.m_capacity = received_size; + #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS + ++this->num_shrink; + #endif + } + } + } + } + + template + void priv_range_insert(pointer pos, FwdIt first, FwdIt last, std::forward_iterator_tag) + { + if(first != last){ + const size_type n = std::distance(first, last); + containers_detail::advanced_insert_aux_proxy proxy(first, last); + priv_range_insert(pos, n, proxy); + } + } + + void priv_range_insert(pointer pos, const size_type n, advanced_insert_aux_int_t &interf) + { + //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 ret; + size_type real_cap = this->members_.m_capacity; + + //Check if we already have room + if (n <= remaining){ + same_buffer_start = true; + } + 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; + } + } + + //If we had room or we have expanded forward + if (same_buffer_start){ + #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS + ++this->num_expand_fwd; + #endif + this->priv_range_insert_expand_forward + (containers_detail::get_pointer(pos), n, interf); + } + //Backwards (and possibly forward) expansion + else if(ret.second){ + #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS + ++this->num_expand_bwd; + #endif + this->priv_range_insert_expand_backwards + ( containers_detail::get_pointer(ret.first) + , real_cap + , containers_detail::get_pointer(pos) + , n + , interf); + } + //New buffer + else{ + #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS + ++this->num_alloc; + #endif + this->priv_range_insert_new_allocation + ( containers_detail::get_pointer(ret.first) + , real_cap + , containers_detail::get_pointer(pos) + , n + , interf); + } + } + + void priv_range_insert_expand_forward(T* pos, size_type n, advanced_insert_aux_int_t &interf) + { + //n can't be 0, because there is nothing to do in that case + if(!n) return; + //There is enough memory + T* old_finish = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size; + const size_type elems_after = old_finish - pos; + + if (elems_after > n){ + //New elements can be just copied. + //Move to uninitialized memory last objects + ::boost::uninitialized_move(old_finish - n, old_finish, old_finish); + this->members_.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_all_to(pos); + } + 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::uninitialized_move + ( pos, old_finish, containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size); + this->members_.m_size += elems_after; + //Copy first new elements in pos + interf.copy_all_to(pos); + } + } + + void priv_range_insert_new_allocation + (T* new_start, size_type new_cap, T* pos, size_type n, advanced_insert_aux_int_t &interf) + { + //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, 0u); + + //Initialize with [begin(), pos) old buffer + //the start of the new buffer + T *old_buffer = containers_detail::get_pointer(this->members_.m_start); + if(old_buffer){ + new_finish = ::boost::uninitialized_move + (containers_detail::get_pointer(this->members_.m_start), pos, old_finish = new_finish); + constructed_values_destroyer.increment_size(new_finish - old_finish); + } + //Initialize new objects, starting from previous point + interf.uninitialized_copy_all_to(old_finish = new_finish); + new_finish += n; + constructed_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::uninitialized_move + (pos, old_buffer + this->members_.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); + } + this->members_.m_start = new_start; + this->members_.m_size = new_finish - new_start; + this->members_.m_capacity = new_cap; + //All construction successful, disable rollbacks + constructed_values_destroyer.release(); + scoped_alloc.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) + { + //n can be zero to just expand capacity + //Backup old data + T* old_start = containers_detail::get_pointer(this->members_.m_start); + T* old_finish = old_start + this->members_.m_size; + size_type old_size = this->members_.m_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); + + //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; + + //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, 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)){ + //Copy first old values before pos, after that the new objects + ::boost::uninitialized_move(old_start, pos, new_start); + this->members_.m_size = elemsbefore; + interf.uninitialized_copy_all_to(new_start + elemsbefore); + this->members_.m_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)){ + //Old situation: + // _________________________________________________________ + //| raw_mem | old_begin | old_end | + //| __________________________________|___________|_________| + // + //New situation: + // _________________________________________________________ + //| old_begin | new | old_end | raw_mem | + //|___________|__________|_________|________________________| + // + //Now initialize the rest of memory with the last old values + ::boost::uninitialized_move + (pos, old_finish, new_start + elemsbefore + n); + //All new elements correctly constructed, avoid new element destruction + this->members_.m_size = old_size + n; + //Old values destroyed automatically with "old_values_destroyer" + //when "old_values_destroyer" goes out of scope unless the have trivial + //destructor after move. + if(value_traits::trivial_dctr_after_move) + old_values_destroyer.release(); + } + //s_before is so big that divides old_end + else{ + //Old situation: + // __________________________________________________ + //| raw_mem | old_begin | old_end | + //| ___________________________|___________|_________| + // + //New situation: + // __________________________________________________ + //| old_begin | new | old_end | raw_mem | + //|___________|__________|_________|_________________| + // + //Now initialize the rest of memory with the last old values + //All new elements correctly constructed, avoid new element destruction + 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::uninitialized_move(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; + } + } + else{ + //Check if we have to do the insertion in two phases + //since maybe s_before is not big enough and + //the buffer was expanded both sides + // + //Old situation: + // _________________________________________________ + //| raw_mem | old_begin + old_end | raw_mem | + //|_________|_____________________|_________________| + // + //New situation with do_after: + // _________________________________________________ + //| old_begin + new + old_end | raw_mem | + //|___________________________________|_____________| + // + //New without do_after: + // _________________________________________________ + //| old_begin + new + old_end | raw_mem | + //|____________________________|____________________| + // + bool do_after = n > s_before; + + //Now we can have two situations: the raw_mem of the + //beginning divides the old_begin, or the new elements: + if (s_before <= elemsbefore) { + //The raw memory divides the old_begin group: + // + //If we need two phase construction (do_after) + //new group is divided in new = new_beg + new_end groups + //In this phase only new_beg will be inserted + // + //Old situation: + // _________________________________________________ + //| raw_mem | old_begin | old_end | raw_mem | + //|_________|___________|_________|_________________| + // + //New situation with do_after(1): + //This is not definitive situation, the second phase + //will include + // _________________________________________________ + //| old_begin | new_beg | old_end | raw_mem | + //|___________|_________|_________|_________________| + // + //New situation without do_after: + // _________________________________________________ + //| old_begin | new | old_end | raw_mem | + //|___________|_____|_________|_____________________| + // + //Copy the first part of old_begin to raw_mem + T *start_n = old_start + difference_type(s_before); + ::boost::uninitialized_move(old_start, start_n, 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); + if(do_after){ + //Now copy the new_beg elements + interf.copy_some_and_update(next, s_before, true); + } + else{ + //Now copy the all the new elements + interf.copy_all_to(next); + T* move_start = next + n; + //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; + } + } + else { + //If we have to expand both sides, + //we will play if the first new values so + //calculate the upper bound of new values + + //The raw memory divides the new elements + // + //If we need two phase construction (do_after) + //new group is divided in new = new_beg + new_end groups + //In this phase only new_beg will be inserted + // + //Old situation: + // _______________________________________________________ + //| raw_mem | old_begin | old_end | raw_mem | + //|_______________|___________|_________|_________________| + // + //New situation with do_after(): + // ____________________________________________________ + //| old_begin | new_beg | old_end | raw_mem | + //|___________|_______________|_________|______________| + // + //New situation without do_after: + // ______________________________________________________ + //| old_begin | new | old_end | raw_mem | + //|___________|_____|_________|__________________________| + // + //First copy whole old_begin and part of new to raw_mem + ::boost::uninitialized_move(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; + //The buffer is all constructed until old_end, + //release destroyer and update size + old_values_destroyer.release(); + + if(do_after){ + //Copy new_beg part + interf.copy_some_and_update(old_start, s_before - mid_n, true); + } + else{ + //Copy all new elements + interf.copy_all_to(old_start); + T* move_start = old_start + (n-mid_n); + //Displace old_end + 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; + } + } + + //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 + // + //Old situation: + // ______________________________________________________ + //| raw_mem | old_begin | old_end | raw_mem | + //|______________|___________|____________|______________| + // + //New situation with do_after(1): + // _______________________________________________________ + //| old_begin + new_beg | new_end |old_end | raw_mem | + //|__________________________|_________|________|_________| + // + //New situation with do_after(2): + // ______________________________________________________ + //| old_begin + new | old_end |raw | + //|_______________________________________|_________|____| + // + const size_type n_after = n - s_before; + const difference_type elemsafter = old_size - elemsbefore; + + //We can have two situations: + if (elemsafter > difference_type(n_after)){ + //The raw_mem from end will divide displaced old_end + // + //Old situation: + // ______________________________________________________ + //| raw_mem | old_begin | old_end | raw_mem | + //|______________|___________|____________|______________| + // + //New situation with do_after(1): + // _______________________________________________________ + //| old_begin + new_beg | new_end |old_end | raw_mem | + //|__________________________|_________|________|_________| + // + //First copy the part of old_end raw_mem + T* finish_n = old_finish - difference_type(n_after); + ::boost::uninitialized_move(finish_n, old_finish, old_finish); + this->members_.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_all_to(pos); + } + else { + //The raw_mem from end will divide new_end part + // + //Old situation: + // _____________________________________________________________ + //| raw_mem | old_begin | old_end | raw_mem | + //|______________|___________|____________|_____________________| + // + //New situation with do_after(2): + // _____________________________________________________________ + //| old_begin + new_beg | new_end |old_end | raw_mem | + //|__________________________|_______________|________|_________| + // + 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::uninitialized_move(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_all_to(pos); + } + } + } + } + + template + void priv_range_insert(const_iterator pos, InIt first, InIt last, std::input_iterator_tag) + { + for(;first != last; ++first){ + this->insert(pos, ::boost::move(value_type(*first))); + } + } + + template + 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; + } + + 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); + } + } + + template + 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 ret; + size_type real_cap = this->members_.m_capacity; + + 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 = containers_detail::get_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 + // iG std::uninitialized_copy(mid, last, end); + ::boost::uninitialized_copy_or_move(mid, last, end); + this->members_.m_size = n; + } + } + else if(!ret.second){ + typename value_traits::ArrayDeallocator scoped_alloc(ret.first, this->alloc(), real_cap); + // iG std::uninitialized_copy(first, last, containers_detail::get_pointer(ret.first)); + ::boost::uninitialized_copy_or_move(first, last, containers_detail::get_pointer(ret.first)); + scoped_alloc.release(); + //Destroy and deallocate old buffer + if(this->members_.m_start != 0){ + this->destroy_n(containers_detail::get_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 = containers_detail::get_pointer(this->members_.m_start); + size_type old_size = this->members_.m_size; + typename value_traits::OldArrayDestructor old_values_destroyer(old_start, 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 - containers_detail::get_pointer(ret.first); + size_type first_count = containers_detail::min_value(n, old_offset); + + FwdIt mid = first; + std::advance(mid, first_count); + // iG std::uninitialized_copy(first, mid, containers_detail::get_pointer(ret.first)); + ::boost::uninitialized_copy_or_move(first, mid, containers_detail::get_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 = containers_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; + } + this->members_.m_size = n; + } + } + } + + template + void priv_assign_dispatch(Integer n, Integer val, containers_detail::true_) + { this->assign((size_type) n, (value_type)val); } + + template + void priv_assign_dispatch(InIt first, InIt last, containers_detail::false_) + { + //Dispatch depending on integer/iterator + typedef typename std::iterator_traits::iterator_category ItCat; + this->priv_assign_aux(first, last, ItCat()); + } + + template + void priv_insert_dispatch(const_iterator pos, Integer n, Integer val, containers_detail::true_) + { this->insert(pos, (size_type)n, (T)val); } + + template + void priv_insert_dispatch(const_iterator pos, InIt first, + InIt last, containers_detail::false_) + { + //Dispatch depending on integer/iterator + typedef typename std::iterator_traits::iterator_category ItCat; + this->priv_range_insert(pos.get_ptr(), 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"); + } + + #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS + public: + unsigned int num_expand_fwd; + unsigned int num_expand_bwd; + unsigned int num_shrink; + unsigned int num_alloc; + void reset_alloc_stats() + { num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0; } + #endif + /// @endcond +}; + +template +inline bool +operator==(const vector& x, const vector& y) +{ + //Check first size and each element if needed + return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); +} + +template +inline bool +operator!=(const vector& x, const vector& y) +{ + //Check first size and each element if needed + return x.size() != y.size() || !std::equal(x.begin(), x.end(), y.begin()); +} + +template +inline bool +operator<(const vector& x, const vector& y) +{ + return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); +} + +template +inline void swap(vector& x, vector& y) +{ x.swap(y); } + +}} + +/// @cond + +namespace boost { + +/* + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + static const bool value = has_trivial_destructor::value; +}; + +*/ + +} + +/// @endcond + +#include + +#endif // #ifndef BOOST_CONTAINERS_CONTAINERS_VECTOR_HPP + From 46d4f1e29483b80d9e1f2735a20245d4c3e7e3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 26 Aug 2011 18:26:44 +0000 Subject: [PATCH 03/14] First inclusion in the repository [SVN r74077] --- doc/Jamfile.v2 | 48 ++ doc/container.qbk | 580 ++++++++++++++++++++++++ doc/html/boostbook.css | 537 ++++++++++++++++++++++ doc/html/images/blank.png | Bin 0 -> 374 bytes doc/html/images/caution.png | Bin 0 -> 1250 bytes doc/html/images/draft.png | Bin 0 -> 17454 bytes doc/html/images/home.png | Bin 0 -> 358 bytes doc/html/images/important.png | Bin 0 -> 722 bytes doc/html/images/next.png | Bin 0 -> 336 bytes doc/html/images/note.png | Bin 0 -> 490 bytes doc/html/images/prev.png | Bin 0 -> 334 bytes doc/html/images/stable_vector.png | Bin 0 -> 7163 bytes doc/html/images/tip.png | Bin 0 -> 449 bytes doc/html/images/toc-blank.png | Bin 0 -> 318 bytes doc/html/images/toc-minus.png | Bin 0 -> 259 bytes doc/html/images/toc-plus.png | Bin 0 -> 264 bytes doc/html/images/up.png | Bin 0 -> 370 bytes doc/html/images/warning.png | Bin 0 -> 1241 bytes doc/html/index.html | 110 +++++ doc/html/reference.css | 12 + example/Jamfile.v2 | 34 ++ example/doc_emplace.cpp | 44 ++ example/doc_move_containers.cpp | 54 +++ example/doc_recursive_containers.cpp | 61 +++ example/doc_type_erasure.cpp | 91 ++++ index.html | 14 + proj/to-do.txt | 2 + proj/vc7ide/container.sln | 87 ++++ proj/vc7ide/container.vcproj | 318 +++++++++++++ proj/vc7ide/deque_test.vcproj | 138 ++++++ proj/vc7ide/flat_tree_test.vcproj | 140 ++++++ proj/vc7ide/list_ex.vcproj | 140 ++++++ proj/vc7ide/slist_test.vcproj | 138 ++++++ proj/vc7ide/stable_vector_test.vcproj | 133 ++++++ proj/vc7ide/string_test.vcproj | 139 ++++++ proj/vc7ide/tree_test.vcproj | 138 ++++++ proj/vc7ide/vector_test.vcproj | 138 ++++++ test/Jamfile.v2 | 34 ++ test/check_equal_containers.hpp | 76 ++++ test/deque_test.cpp | 295 ++++++++++++ test/dummy_test_allocator.hpp | 157 +++++++ test/emplace_test.hpp | 625 ++++++++++++++++++++++++++ test/expand_bwd_test_allocator.hpp | 193 ++++++++ test/expand_bwd_test_template.hpp | 269 +++++++++++ test/flat_tree_test.cpp | 333 ++++++++++++++ test/heap_allocator_v1.hpp | 159 +++++++ test/list_test.cpp | 78 ++++ test/list_test.hpp | 312 +++++++++++++ test/map_test.hpp | 521 +++++++++++++++++++++ test/movable_int.hpp | 230 ++++++++++ test/print_container.hpp | 64 +++ test/set_test.hpp | 504 +++++++++++++++++++++ test/slist_test.cpp | 82 ++++ test/stable_vector_test.cpp | 86 ++++ test/string_test.cpp | 293 ++++++++++++ test/tree_test.cpp | 233 ++++++++++ test/util.hpp | 113 +++++ test/vector_test.cpp | 127 ++++++ test/vector_test.hpp | 253 +++++++++++ 59 files changed, 8133 insertions(+) create mode 100644 doc/Jamfile.v2 create mode 100644 doc/container.qbk create mode 100644 doc/html/boostbook.css create mode 100644 doc/html/images/blank.png create mode 100644 doc/html/images/caution.png create mode 100644 doc/html/images/draft.png create mode 100644 doc/html/images/home.png create mode 100644 doc/html/images/important.png create mode 100644 doc/html/images/next.png create mode 100644 doc/html/images/note.png create mode 100644 doc/html/images/prev.png create mode 100644 doc/html/images/stable_vector.png create mode 100644 doc/html/images/tip.png create mode 100644 doc/html/images/toc-blank.png create mode 100644 doc/html/images/toc-minus.png create mode 100644 doc/html/images/toc-plus.png create mode 100644 doc/html/images/up.png create mode 100644 doc/html/images/warning.png create mode 100644 doc/html/index.html create mode 100644 doc/html/reference.css create mode 100644 example/Jamfile.v2 create mode 100644 example/doc_emplace.cpp create mode 100644 example/doc_move_containers.cpp create mode 100644 example/doc_recursive_containers.cpp create mode 100644 example/doc_type_erasure.cpp create mode 100644 index.html create mode 100644 proj/to-do.txt create mode 100644 proj/vc7ide/container.sln create mode 100644 proj/vc7ide/container.vcproj create mode 100644 proj/vc7ide/deque_test.vcproj create mode 100644 proj/vc7ide/flat_tree_test.vcproj create mode 100644 proj/vc7ide/list_ex.vcproj create mode 100644 proj/vc7ide/slist_test.vcproj create mode 100644 proj/vc7ide/stable_vector_test.vcproj create mode 100644 proj/vc7ide/string_test.vcproj create mode 100644 proj/vc7ide/tree_test.vcproj create mode 100644 proj/vc7ide/vector_test.vcproj create mode 100644 test/Jamfile.v2 create mode 100644 test/check_equal_containers.hpp create mode 100644 test/deque_test.cpp create mode 100644 test/dummy_test_allocator.hpp create mode 100644 test/emplace_test.hpp create mode 100644 test/expand_bwd_test_allocator.hpp create mode 100644 test/expand_bwd_test_template.hpp create mode 100644 test/flat_tree_test.cpp create mode 100644 test/heap_allocator_v1.hpp create mode 100644 test/list_test.cpp create mode 100644 test/list_test.hpp create mode 100644 test/map_test.hpp create mode 100644 test/movable_int.hpp create mode 100644 test/print_container.hpp create mode 100644 test/set_test.hpp create mode 100644 test/slist_test.cpp create mode 100644 test/stable_vector_test.cpp create mode 100644 test/string_test.cpp create mode 100644 test/tree_test.cpp create mode 100644 test/util.hpp create mode 100644 test/vector_test.cpp create mode 100644 test/vector_test.hpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 0000000..fa1e3a4 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,48 @@ +# Boost.Container library documentation Jamfile --------------------------------- +# +# Copyright Ion Gaztanaga 2009-2011. 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) +# +# See http://www.boost.org for updates, documentation, and revision history. + +import doxygen ; +import quickbook ; + +path-constant images_location : html ; + +doxygen autodoc + : + [ glob ../../../boost/container/*.hpp ] + : + EXTRACT_ALL=NO + HIDE_UNDOC_MEMBERS=YES + EXTRACT_PRIVATE=NO + ENABLE_PREPROCESSING=YES + EXPAND_ONLY_PREDEF=YES + MACRO_EXPANSION=YES + "PREDEFINED=\"insert_const_ref_type= const T&\" \\ + \"BOOST_CONTAINER_DOXYGEN_INVOKED\" \\ + \"BOOST_RV_REF(T)=T &&\" \\ + \"BOOST_COPY_ASSIGN_REF(T)=const T &\" \\ + \"BOOST_RV_REF_2_TEMPL_ARGS(T,a,b)=T &&\" \\ + \"BOOST_RV_REF_3_TEMPL_ARGS(T,a,b,c)=TT &&\" \\ + \"BOOST_FWD_REF(a)=a &&\"" + "boost.doxygen.reftitle=Boost.Container Reference" + ; + +xml container : container.qbk ; + +boostbook standalone + : + container + : + boost.root=../../../.. + boost.libraries=../../../../libs/libraries.htm + generate.section.toc.level=3 + chunk.first.sections=1 + pdf:img.src.path=$(images_location)/ + autodoc + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html + ; diff --git a/doc/container.qbk b/doc/container.qbk new file mode 100644 index 0000000..ce33961 --- /dev/null +++ b/doc/container.qbk @@ -0,0 +1,580 @@ +[/ + / Copyright (c) 2009-2011 Ion Gazta\u00F1aga + / + / 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) + /] + +[library Boost.Container + [quickbook 1.5] + [authors [Gaztanaga, Ion]] + [copyright 2009-2011 Ion Gaztanaga] + [id container] + [dirname container] + [purpose Containers library] + [license + 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]) + ] +] + +[template super[x]''''''[x]''''''] +[template sub[x]''''''[x]''''''] + +[section:intro Introduction] + +[*Boost.Container] library implements several well-known containers, including +STL containers. The aim of the library is to offers advanced features not present +in standard containers or to offer the latest standard draft features for compilers +that comply with C++03. + +In short, what does [*Boost.Container] offer? + +* Move semantics are implemented, including move emulation for pre-C++11 compilers. +* New advanced features (e.g. placement insertion, recursive containers) are present. +* Containers support stateful allocators and are compatible with [*Boost.Interprocess] + (they can be safely placed in shared memory). +* The library offers new useful containers: + * [classref boost::container::flat_map flat_map], + [classref boost::container::flat_map flat_set], + [classref boost::container::flat_map flat_multiset] and + [classref boost::container::flat_map flat_multiset]: drop-in + replacements for standard associative containers but more memory friendly and with faster + searches. + * [classref boost::container::stable_vector stable_vector]: a std::list and std::vector hybrid + container: vector-like random-access iterators and list-like iterator stability in insertions and erasures. + * [classref boost::container::slist slist]: the classic pre-standard singly linked list implementation + offering constant-time `size()`. Note that C++11 `forward_list` has no `size()`. + +[section:introduction_building_container Building Boost.Container] + +There is no need to compile [*Boost.Container], since it's +a header only library. Just include your Boost header directory in your +compiler include path. + +[endsect] + +[section:tested_compilers Tested compilers] + +[*Boost.Container] requires a decent C++98 compatibility. Some compilers known to work are: + +* Visual C++ >= 7.1. +* GCC >= 3.4. +* Intel C++ >= 9.0 + +[endsect] + +[endsect] + +[section:move_emplace Efficient insertion] + +Move semantics and placement insertion are two features brought by C++11 containers +that can have a very positive impacto in your C++ applications. Boost.Container implements +both techniques both for C++11 and C++03 compilers. + +[section:move_containers Move-aware containers] + +All containers offered by [*Boost.Container] can store movable-only types +and actual requirements for `value_type` depend on each container operations. +Following C++11 requirements even for C++03 compilers, many operations now require +movable or default constructible types instead of just copy constructible types. + +Containers themselves are also movable, with no-throw guarantee if allocator +or predicate (if present) copy operations are no-throw. This allows +high performance operations when transfering data between vectors. +Let's see an example: + +[import ../example/doc_move_containers.cpp] +[doc_move_containers] + +[endsect] + +[section:emplace Emplace: Placement insertion] + +All containers offered by [*Boost.Container] implement placement insertion, +which means that objects can be built directly into the container from user arguments +without creating any temporary object. For compilers without variadic templates support +placement insertion is emulated up to a finite (10) number of arguments. + +Expensive to move types are perfect candidates emplace functions and in case of node containers +([classref boost::container::list list], [classref boost::container::set set], ...) +emplace allows storing non-movable and non-copyable types in containers! Let's +see an example: + +[import ../example/doc_emplace.cpp] +[doc_emplace] + +[endsect] + +[endsect] + + +[section:containers_of_incomplete_types Containers of Incomplete Types] + +Incomplete types allow +[@http://en.wikipedia.org/wiki/Type_erasure [*type erasure ]] and +[@http://en.wikipedia.org/wiki/Recursive_data_type [*recursive data types]], and +C and C++ programmers have been using it for years to build complex data structures, like +tree structures where a node may have an arbitrary number of children. + +What about standard containers? Containers of incomplete types have been under discussion for a long time, +as explained in Matt Austern's great article ([@http://drdobbs.com/184403814 [*The Standard Librarian: Containers of Incomplete Types]]): + +["['Unlike most of my columns, this one is about something you can't do with the C++ Standard library: +put incomplete types in one of the standard containers. This column explains why you might want to +do this, why the standardization committee banned it even though they knew it was useful, and what +you might be able to do to get around the restriction.]] + +["['In 1997, shortly before the C++ Standard was completed, the standardization committee received a +query: Is it possible to create standard containers with incomplete types? It took a while for the +committee to understand the question. What would such a thing even mean, and why on earth would you +ever want to do it? The committee eventually worked it out and came up with an answer to the question. +(Just so you don't have to skip ahead to the end, the answer is "no.") But the question is much more +interesting than the answer: it points to a useful, and insufficiently discussed, programming technique. +The standard library doesn't directly support that technique, but the two can be made to coexist.]] + +["['In a future revision of C++, it might make sense to relax the restriction on instantiating +standard library templates with incomplete types. Clearly, the general prohibition should stay +in place - instantiating templates with incomplete types is a delicate business, and there are +too many classes in the standard library where it would make no sense. But perhaps it should be +relaxed on a case-by-case basis, and `vector` looks like a good candidate for such special-case +treatment: it's the one standard container class where there are good reasons to instantiate +it with an incomplete type and where Standard Library implementors want to make it work. As of +today, in fact, implementors would have to go out of their way to prohibit it!]] + +C++11 standard is also cautious about incomplete types and STL: ["['17.6.4.8 Other functions (...) 2. +the effects are undefined in the following cases: (...) In particular - if an incomplete type (3.9) +is used as a template argument when instantiating a template component, +unless specifically allowed for that component]]. Fortunately [*Boost.Container] containers are designed +to support type erasure and recursive types, so let's see some examples: + +[section:recursive_containers Recursive containers] + +All containers offered by [*Boost.Container] can be used to define recursive containers: + +[import ../example/doc_recursive_containers.cpp] +[doc_recursive_containers] + +[endsect] + +[section:type_erasure Type Erasure] + +Containers of incomplete types are useful to break header file dependencies and improve +compilation types. With Boost.Container, you can write a header file defining a class +with containers of incomplete types as data members, if you carefully put all the +implementation details that require knowing the size of the `value_type` in your +implementation file: + +[import ../example/doc_type_erasure.cpp] + +In this header file we define a class (`MyClassHolder)` that holds a `vector` of an +incomplete type (`MyClass`) that it's only forward declared. + +[doc_type_erasure_MyClassHolder_h] + +Then we can define `MyClass` in its own header file. + +[doc_type_erasure_MyClass_h] + +And include it only in the implementation file of `MyClassHolder` + +[doc_type_erasure_MyClassHolder_cpp] + +Finally, we can just compile, link, and run! + +[doc_type_erasure_main_cpp] + +[endsect] + +[endsect] + +[section:non_standard_containers Non-standard containers] + +[section:stable_vector ['stable_vector]] + +This useful, fully STL-compliant stable container [@http://bannalia.blogspot.com/2008/09/introducing-stablevector.html designed by by Joaqu\u00EDn M. L\u00F3pez Mu\u00F1oz] +is an hybrid between `vector` and `list`, providing most of +the features of `vector` except [@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#69 element contiguity]. + +Extremely convenient as they are, `vector`s have a limitation that many novice C++ programmers frequently stumble upon: +iterators and references to an element of an `vector` are invalidated when a preceding element is erased or when the +vector expands and needs to migrate its internal storage to a wider memory region (i.e. when the required size exceeds +the vector's capacity). We say then that `vector`s are unstable: by contrast, stable containers are those for which +references and iterators to a given element remain valid as long as the element is not erased: examples of stable containers +within the C++ standard library are `list` and the standard associative containers (`set`, `map`, etc.). + +Sometimes stability is too precious a feature to live without, but one particular property of `vector`s, element contiguity, +makes it impossible to add stability to this container. So, provided we sacrifice element contiguity, how much +can a stable design approach the behavior of `vector` (random access iterators, amortized constant time end +insertion/deletion, minimal memory overhead, etc.)? +The following image describes the layout of a possible data structure upon which to base the design of a stable vector: + +[$images/stable_vector.png [width 50%] [align center] ] + +Each element is stored in its own separate node. All the nodes are referenced from a contiguous array of pointers, but +also every node contains an "up" pointer referring back to the associated array cell. This up pointer is the key element +to implementing stability and random accessibility: + +Iterators point to the nodes rather than to the pointer array. This ensures stability, as it is only the pointer array +that needs to be shifted or relocated upon insertion or deletion. Random access operations can be implemented by using +the pointer array as a convenient intermediate zone. For instance, if the iterator it holds a node pointer `it.p` and we +want to advance it by n positions, we simply do: + +[c++] + + it.p = *(it.p->up+n); + +That is, we go "up" to the pointer array, add n there and then go "down" to the resulting node. + +[*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 vector. Like vector, iterators are random access. `stable_vector` +does not provide element contiguity; in exchange for this absence, the container is stable, i.e. references and iterators +to an element of a `stable_vector` remain valid as long as the element is not erased, and an iterator that has been +assigned the return value of end() always remain valid until the destruction of the associated `stable_vector`. + +[*Operation complexity]. The big-O complexities of `stable_vector` operations match exactly those of vector. In general, +insertion/deletion is constant time at the end of the sequence and linear elsewhere. Unlike vector, `stable_vector` +does not internally perform any value_type destruction, copy/move construction/assignment operations other than those exactly +corresponding to the insertion of new elements or deletion of stored elements, which can sometimes compensate in terms of +performance for the extra burden of doing more pointer manipulation and an additional allocation per element. + +[*Exception safety]. (according to [@http://www.boost.org/community/exception_safety.html Abrahams' terminology]) +As `stable_vector` does not internally copy/move elements around, some +operations provide stronger exception safety guarantees than in vector: + +[table:stable_vector_req Exception safety + [[operation] [exception safety for `vector`] [exception safety for `stable_vector`]] + [[insert] [strong unless copy/move construction/assignment of `T` throw (basic)] [strong]] + [[erase] [no-throw unless copy/move construction/assignment of `T` throw (basic)] [no-throw]] +] + +[*Memory overhead]. The C++ standard does not specifiy requirements on memory consumption, but virtually any implementation +of `vector` has the same behavior wih respect to memory usage: the memory allocated by a `vector` v with n elements of type T +is + +m[sub v] = c\u2219e, + +where c is `v.capacity()` and e is `sizeof(T)`. c can be as low as n if the user has explicitly reserved the exact capacity +required; otherwise, the average value c for a growing `vector` oscillates between 1.25\u2219n and 1.5\u2219n for typical resizing +policies. For `stable_vector`, the memory usage is + +m[sub sv] = (c + 1)p + (n + 1)(e + p), + +where p is the size of a pointer. We have c + 1 and n + 1 rather than c and n because a dummy node is needed at the end of +the sequence. If we call f the capacity to size ratio c/n and assume that n is large enough, we have that + +m[sub sv]/m[sub v] \u2243 (fp + e + p)/fe. + +So, `stable_vector` uses less memory than `vector` only when e > p and the capacity to size ratio exceeds a given threshold: + +m[sub sv] < m[sub v] <-> f > (e + p)/(e - p). (provided e > p) + +This threshold approaches typical values of f below 1.5 when e > 5p; in a 32-bit architecture, when e > 20 bytes. + +[*Summary]. `stable_vector` is a drop-in replacement for `vector` providing stability of references and iterators, in exchange +for missing element contiguity and also some performance and memory overhead. When the element objects are expensive to +move around, the performance overhead can turn into a net performance gain for `stable_vector` if many middle insertions +or deletions are performed or if resizing is very frequent. Similarly, if the elements are large there are situations when +the memory used by `stable_vector` can actually be less than required by vector. + +['Note: Text and explanations taken from [@http://bannalia.blogspot.com/2008/09/introducing-stablevector.html Joaqu\u00EDn's blog]] + +[endsect] + +[section:flat_xxx ['flat_(multi)map/set] associative containers] + +Using sorted vectors instead of tree-based associative containers is a well-known technique in +C++ world. Matt Austern's classic article +[@http://lafstern.org/matt/col1.pdf Why You Shouldn't Use set, and What You Should Use Instead] +(C++ Report 12:4, April 2000) was enlightening: + +["['Red-black trees aren't the only way to organize data that permits lookup in logarithmic time. One of the basic +algorithms of computer science is binary search, which works by successively dividing a range in half. Binary +search is log N and it doesn't require any fancy data structures, just a sorted collection of elements. +(...) You can use whatever data structure is convenient, so long as it provides STL iterator; +usually it's easiest to use a C array, or a vector.]] + +["['Both std::lower_bound and set::find take time proportional to log N, but the constants of proportionality +are very different. Using g++ (...) it takes X seconds to perform a million lookups in a +sorted vector of a million elements, and almost twice as long (...) using a set. Moreover, +the set uses almost three times as much memory (48 million bytes) as the vector (16.8 million).]] + +["['Using a sorted vector instead of a set gives you faster lookup and much faster iteration, +but at the cost of slower insertion. Insertion into a set, using set::insert, is proportional +to log N, but insertion into a sorted vector, (...) +, is proportional to N. Whenever you insert something into a vector, +vector::insert has to make room by shifting all of the elements that follow it. On average, if you're equally +likely to insert a new element anywhere, you'll be shifting N/2 elements.]] + +["['It may sometimes be convenient to bundle all of this together into a small container adaptor. +This class does not satisfy the requirements of a Standard Associative Container, since the complexity of insert is +O(N) rather than O(log N), but otherwise it is almost a drop-in replacement for set.]] + +Following Matt Austerns indications, Andrei Alexandrescu's +[@http://www.bestwebbuys.com/Modern-C-Design-Generic-Programming-and-Design-Patterns-Applied-ISBN-9780201704310?isrc=-rd Modern C++ Design] +showed `AssocVector`, a `std::map` drop-in +replacement designed in his [@http://loki-lib.sourceforge.net/ Loki] library: + +["['It seems as if we're better off with a sorted vector. The disadvantages of a sorted +vector are linear-time insertions and linear-time deletions (...). In exchange, a vector +offers about twice the lookup speed and a much smaller working set (...). +Loki saves the trouble of maintaining a sorted vector by hand by defining an AssocVector class +template. AssocVector is a drop-in replacement for std::map (it supports the same set of member +functions), implemented on top of std::vector. AssocVector differs from a map in the behavior of +its erase functions (AssocVector::erase invalidates all iterators into the object) and in the +complexity guarantees of insert and erase (linear as opposed to constant). ]] + +[*Boost.Container] `flat_[multi]map/set` containers are ordered-vector based associative containers +based on Austern's and Alexandrescu's guidelines. These ordered vector containers have also +benefited recently with the addition of `move semantics` to C++, speeding up insertion +and erasure times considerably. Flat associative containers have the following +attributes: + +* Faster lookup than standard associative containers +* Much faster iteration than standard associative containers +* Less memory consumption for small objects (and for big objects if `shrink_to_fit` is used) +* Improved cache performance (data is stored in contiguous memory) +* Non-stable iterators (iterators are invalidated when inserting and erasing elements) +* Non-copyable and non-movable values types can't be stored +* Weaker exception safety than standard associative containers +(copy/move constructors can throw when shifting values in erasures and insertions) +* Slower insertion and erasure than standard associative containers (specially for non-movable types) + +[endsect] + +[section:slist ['slist]] + +When the standard template library was designed, it contained a singly linked list called `slist`. +Unfortunately, this container was not standardized and remained as an extension for many standard +library implementations until C++11 introduced `forward_list`, which is a bit different from the +the original SGI `slist`. According to [@http://www.sgi.com/tech/stl/Slist.html SGI STL documentation]: + +["['An `slist` is a singly linked list: a list where each element is linked to the next element, but +not to the previous element. That is, it is a Sequence that supports forward but not backward traversal, +and (amortized) constant time insertion and removal of elements. Slists, like lists, have the important +property that insertion and splicing do not invalidate iterators to list elements, and that even removal +invalidates only the iterators that point to the elements that are removed. The ordering of iterators +may be changed (that is, slist::iterator might have a different predecessor or successor after a list +operation than it did before), but the iterators themselves will not be invalidated or made to point to +different elements unless that invalidation or mutation is explicit.]] + +["['The main difference between `slist` and list is that list's iterators are bidirectional iterators, +while slist's iterators are forward iterators. This means that `slist` is less versatile than list; +frequently, however, bidirectional iterators are unnecessary. You should usually use `slist` unless +you actually need the extra functionality of list, because singly linked lists are smaller and faster +than double linked lists.]] + +["['Important performance note: like every other Sequence, `slist` defines the member functions insert and erase. +Using these member functions carelessly, however, can result in disastrously slow programs. The problem is that +insert's first argument is an iterator pos, and that it inserts the new element(s) before pos. This means that +insert must find the iterator just before pos; this is a constant-time operation for list, since list has +bidirectional iterators, but for `slist` it must find that iterator by traversing the list from the beginning +up to pos. In other words: insert and erase are slow operations anywhere but near the beginning of the slist.]] + +["['Slist provides the member functions insert_after and erase_after, which are constant time operations: you should +always use insert_after and erase_after whenever possible. If you find that insert_after and erase_after aren't +adequate for your needs, and that you often need to use insert and erase in the middle of the list, then you +should probably use list instead of slist.]] + +[*Boost.Container] updates the classic `slist` container with C++11 features like move semantics and placement +insertion and implements it a bit differently for the standard C++11 `forward_list`. `forward_list` has no `size()` +method, so it's been designed to allow (or in practice, encourage) implementations without tracking list size +with every insertion/erasure, allowing constant-time +`splice_after(iterator, forward_list &, iterator, iterator)`-based list merging. On the other hand `slist` offers +constant-time `size()` for those that don't care about linear-time `splice_after(iterator, slist &, iterator, iterator)` +`size()` and offers an additional `splice_after(iterator, slist &, iterator, iterator, size_type)` method that +can speed up `slist` merging when the programmer already knows the size. `slist` and `forward_list` are therefore +complementary. + +[endsect] + +[endsect] + +[section:Cpp11_conformance C++11 Conformance] + +[*Boost.Container] aims for full C++11 conformance except reasoned deviations, +backporting as much as possible for C++03. Obviously, this conformance is a work +in progress so this section explains what C++11 features are implemented and which of them +have been backported to C++03 compilers. + +[section:move_emplace Move and Emplace] + +For compilers with rvalue references and for those C++03 types that use +[@http://www.boost.org/libs/move Boost.Move] rvalue reference emulation +[*Boost.Container] supports all C++11 features related to move semantics: containers +are movable, requirements for `value_type` are those specified for C++11 containers. + +For compilers with variadic templates, [*Boost.Container] supports placement insertion +(`emplace`, ...) functions from C++11. For those compilers without variadic templates +support [*Boost.Container] uses the preprocessor to create a set of overloads up to +a finite (10) number of parameters. + +[endsect] + +[section:alloc_traits_move_traits Stateful allocators and Scoped allocators] + +C++03 was not stateful-allocator friendly. For compactness of container objects and for +simplicity, it did not require containers to support allocators with state: Allocator objects +need not be stored in container objects. It was not possible to store an allocator with state, +say an allocator that holds a pointer to an arena from which to allocate. C++03 allowed implementors +to suppose two allocators of the same type always compare equal (that means that memory allocated +by one allocator object could be deallocated by another instance of the same type) and +allocators were not swapped when the container was swapped. + +Many C++ container implementors felt C++03 guarantees were too weak and started to offer extensions. +[*Boost.Container], following [@http://www.boost.org/libs/interprocess/ Boost.Interprocess] +containers experience supporting stateful allocators, offers the following guarantees: + +* Allocators are copy-constructed in copy/move constructors +* If possible, asingle allocator is hold to construct `value_type` and this allocator is copy constructed + from the user-supplied allocator object during container's contructor. If the container needs an auxiliary + allocator (e.g. a array allocator used by `deque` or `stable_vector`), that allocator is also + copy-constructed from the user-supplied allocator when the container is constructed (i.e. it's + not constructed on the fly when auxiliary memory is needed). +* Allocators are compared for equality when swapping containers. If allocators dont' compare + equal allocators are swapped using an unqualified `swap` call. + +C++11 further improves stateful allocator support through the +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2554.pdf +Scoped Allocators model], using classes like `std::scoped_allocator_adaptor` and `std::allocator_traits`. +[*Boost.Container does not support it yet, but there are plans to do so and backport scoped allocator +support to C++03 compilers. + +[endsect] + +[section:initializer_lists Initializer lists] + +[*Boost.Container] does not support initializer lists when constructing or assigning containers +but it will support it for compilers with initialized-list support. This feature won't be backported +to C++03 compilers. + +[endsect] + +[section:Vector_bool vector] + +`vector` specialization has been quite problematic, and there have been several +unsuccessful tries to deprecate or remove it from the standard. [*Boost.Container] does not implement it +as there is a superior [@http://www.boost.org/libs/dynamic_bitset/ Boost.DynamicBitset] +solution. For issues with `vector` see papers +[@http://www.gotw.ca/publications/N1211.pdf vector: N1211: More Problems, Better Solutions], +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2160.html N2160: Library Issue 96: Fixing vector], +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2204.html N2204 A Specification to deprecate vector]. + +* ["['In 1998, admitting that the committee made a mistake was controversial. + Since then Java has had to deprecate such significant portions of their libraries + that the idea C++ would be ridiculed for deprecating a single minor template specialization seems quaint.]] + +* ["['`vector` is not a container and `vector::iterator` is not a random-access iterator +(or even a forward or bidirectional iterator either, for that matter). This has already broken user code +in the field in mysterious ways.]] + +* ["['`vector` forces a specific (and potentially bad) optimization choice on all users by enshrining +it in the standard. The optimization is premature; different users have different requirements. This too +has already hurt users who have been forced to implement workarounds to disable the 'optimization' +(e.g., by using a vector and manually casting to/from bool).]] + +So `boost::container::vector::iterator` returns real `bool` references and works as a fully compliant container. +If you need a memory optimized version of `boost::container::vector` functionalities, please use +[@http://www.boost.org/libs/dynamic_bitset/ Boost.DynamicBitset]. + +[endsect] + +[endsect] + +[section:other_features Other features] + +* Default constructors don't allocate memory which improves performance and + usually implies a no-throw guarantee (if predicate's or allocator's default constructor doesn't throw). + +* Small string optimization for [classref boost::container::basic_string basic_string], + with an internal buffer of 11/23 bytes (32/64 bit systems) + [*without] increasing the usual `sizeof` of the string (3 words). + +* `[multi]set/map` containers are size optimized embedding the color bit of the red-black trees into + the parent pointer. + +* `[multi]set/map` containers use no recursive functions so stack problems are avoided. + +[endsect] + +[section:history_and_reasons History and reasons to use Boost.Container] + +[section:boost_container_history Boost.Container history] + +[*Boost.Container] is a product of a long development effort that started with the experimental Shmem library, +which pioneered the use of standard containers in shared memory. Shmem included modified SGI STL container +code tweaked to support non-raw `allocator::pointer` types and stateful allocators. Once reviewed, +Shmem was accepted as [@http://www.boost.org/libs/interprocess/ Boost.Interprocess] and this library +continued to refine and improve those containers. + +In 2007, container code from node containers (`map`, `list`, `slist`) was rewritten, refactored +and expanded to build the intrusive container library [@http://www.boost.org/libs/intrusive/ Boost.Intrusive]. +[*Boost.Interprocess] containers were refactored to take advantage of [*Boost.Intrusive] containers and +code duplication was minimized. Both libraries continued to gain support and bug fixes for years. +They introduced move semantics, emplacement insertion and more features of then unreleased C++0x +standard. + +[*Boost.Interprocess] containers were always standard compliant, and those containers and new +containers like `stable_vector` and `flat_[multi]set/map` were used outside [*Boost.Interprocess] +with success. As containers were mature enough to get their own library, it was a natural step to +collect them containers and build [*Boost.Container], a library targeted to a wider audience. + +[endsect] + + +[section:Why_boost_container Why Boost.Container?] + +With so many high quality standard library implemenations out there, why would you want to +use [*Boost.Container]? There are several reasons for that: + +* If you have a C++03 compiler, you can have access to C++11 features and have an easy + code migration when you change your compiler. +* It's compatible with [*Boost.Interprocess] shared memory allocators. +* You have extremely useful new containers like `stable_vector` and `flat_[multi]set/map`. +* If you work on multiple plataforms, you'll have a portable behaviour without depending + on the std-lib implementation conformance of each platform. Some examples: + * Default constructors don't allocate memory at all, which improves performance and + usually implies a no-throw guarantee (if predicate's or allocator's default constructor doesn't throw). + * Small string optimization for [classref boost::container::basic_string basic_string]. +* New extensions beyond the standard based on user feedbak to improve code performance. + +[endsect] + +[endsect] + + + + +[section:acknowledgements_notes Acknowledgements, notes and links] + +* Original standard container code comes from [@http://www.sgi.com/tech/stl/ SGI STL library], + which enhanced the original HP STL code. Most of this code was rewritten for + [*Boost.Interprocess] and moved to [*Boost.Intrusive]. `deque` and `string` containers still + have fragments of the original SGI code. Many thanks to Alexander Stepanov, Meng Lee, and David Musser, + Matt Austern, and all HP and SGI STL developers. + +* `flat_[multi]_map/set` containers were originally based on [@http://en.wikipedia.org/wiki/Loki_%28C%2B%2B%29 Loki's] + AssocVector class. Code was rewritten and expanded for [*Boost.Interprocess], so thanks to Andrei Alexandrescu. + +* `stable_vector` was invented and coded by + [@http://bannalia.blogspot.com/2008/09/introducing-stablevector.html Joaqu\u00EDn M. L\u00F3pez Mu\u00F1oz], + then adapted for [*Boost.Interprocess]. Thanks for such a great container. + +* Howard Hinnant's help and experience was essential when implementing move semantics, + improving allocator support and implementing small string optimization. Thanks Howard + for your wonderful standard library implementations. + +* And finally thanks to all Boosters who helped all these years, improving, fixing and + reviewing the library. + +[endsect] + +[section:release_notes Release Notes] + +* First release with Boost 1.48. Container code from [*Boost.Interprocess] was deleted + and redirected to [*Boost.Container ] via using directives. + +[endsect] + +[xinclude autodoc.xml] diff --git a/doc/html/boostbook.css b/doc/html/boostbook.css new file mode 100644 index 0000000..2146334 --- /dev/null +++ b/doc/html/boostbook.css @@ -0,0 +1,537 @@ +/*============================================================================= + Copyright (c) 2004 Joel de Guzman + + 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) +=============================================================================*/ + +/*============================================================================= + Body defaults +=============================================================================*/ + + body + { + margin: 1em; + font-family: sans-serif; + } + +/*============================================================================= + Paragraphs +=============================================================================*/ + + p + { + text-align: left; + font-size: 10pt; + line-height: 1.15; + } + +/*============================================================================= + Program listings +=============================================================================*/ + + /* Code on paragraphs */ + p tt.computeroutput + { + font-size: 10pt; + } + + pre.synopsis + { + font-size: 10pt; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + .programlisting, + .screen + { + font-size: 10pt; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + +/*============================================================================= + Headings +=============================================================================*/ + + h1, h2, h3, h4, h5, h6 + { + text-align: left; + margin: 1em 0em 0.5em 0em; + font-weight: bold; + } + + h1 { font: 140% } + h2 { font: bold 140% } + h3 { font: bold 130% } + h4 { font: bold 120% } + h5 { font: italic 110% } + h6 { font: italic 100% } + + /* Top page titles */ + title, + h1.title, + h2.title + h3.title, + h4.title, + h5.title, + h6.title, + .refentrytitle + { + font-weight: bold; + margin-bottom: 1pc; + } + + h1.title { font-size: 140% } + h2.title { font-size: 140% } + h3.title { font-size: 130% } + h4.title { font-size: 120% } + h5.title { font-size: 110% } + h6.title { font-size: 100% } + + .section h1 + { + margin: 0em 0em 0.5em 0em; + font-size: 140%; + } + + .section h2 { font-size: 140% } + .section h3 { font-size: 130% } + .section h4 { font-size: 120% } + .section h5 { font-size: 110% } + .section h6 { font-size: 100% } + + /* Code on titles */ + h1 tt.computeroutput { font-size: 140% } + h2 tt.computeroutput { font-size: 140% } + h3 tt.computeroutput { font-size: 130% } + h4 tt.computeroutput { font-size: 120% } + h5 tt.computeroutput { font-size: 110% } + h6 tt.computeroutput { font-size: 100% } + +/*============================================================================= + Author +=============================================================================*/ + + h3.author + { + font-size: 100% + } + +/*============================================================================= + Lists +=============================================================================*/ + + li + { + font-size: 10pt; + line-height: 1.3; + } + + /* Unordered lists */ + ul + { + text-align: left; + } + + /* Ordered lists */ + ol + { + text-align: left; + } + +/*============================================================================= + Links +=============================================================================*/ + + a + { + text-decoration: none; /* no underline */ + } + + a:hover + { + text-decoration: underline; + } + +/*============================================================================= + Spirit style navigation +=============================================================================*/ + + .spirit-nav + { + text-align: right; + } + + .spirit-nav a + { + color: white; + padding-left: 0.5em; + } + + .spirit-nav img + { + border-width: 0px; + } + +/*============================================================================= + Table of contents +=============================================================================*/ + + .toc + { + margin: 1pc 4% 0pc 4%; + padding: 0.1pc 1pc 0.1pc 1pc; + font-size: 10pt; + line-height: 1.15; + } + + .toc-main + { + width: 600; + text-align: center; + margin: 1pc 1pc 1pc 10%; + padding: 2pc 1pc 3pc 1pc; + line-height: 0.1; + } + + .boost-toc + { + float: right; + padding: 0.5pc; + } + +/*============================================================================= + Tables +=============================================================================*/ + + .table-title, + div.table p.title + { + margin-left: 4%; + padding-right: 0.5em; + padding-left: 0.5em; + } + + .informaltable table, + .table table + { + width: 92%; + margin-left: 4%; + margin-right: 4%; + } + + div.informaltable table, + div.table table + { + padding: 4px; + } + + /* Table Cells */ + div.informaltable table tr td, + div.table table tr td + { + padding: 0.5em; + text-align: left; + } + + div.informaltable table tr th, + div.table table tr th + { + padding: 0.5em 0.5em 0.5em 0.5em; + border: 1pt solid white; + font-size: 120%; + } + +/*============================================================================= + Blurbs +=============================================================================*/ + + div.note, + div.tip, + div.important, + div.caution, + div.warning, + p.blurb + { + font-size: 10pt; + line-height: 1.2; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + p.blurb img + { + padding: 1pt; + } + +/*============================================================================= + Variable Lists +=============================================================================*/ + + span.term + { + font-weight: bold; + font-size: 10pt; + } + + div.variablelist table tbody tr td + { + text-align: left; + vertical-align: top; + padding: 0em 2em 0em 0em; + font-size: 10pt; + } + + div.variablelist table tbody tr td p + { + margin: 0em 0em 0.5em 0em; + } + + /* Make the terms in definition lists bold */ + div.variablelist dl dt + { + font-weight: bold; + font-size: 10pt; + } + + div.variablelist dl dd + { + margin: 1em 0em 1em 2em; + font-size: 10pt; + } + +/*============================================================================= + Misc +=============================================================================*/ + + /* Title of books and articles in bibliographies */ + span.title + { + font-style: italic; + } + + span.underline + { + text-decoration: underline; + } + + span.strikethrough + { + text-decoration: line-through; + } + + /* Copyright, Legal Notice */ + div div.legalnotice p + { + font-size: 8pt; + text-align: left + } + +/*============================================================================= + Colors +=============================================================================*/ + + @media screen + { + /* Links */ + a + { + color: #0C7445; + } + + a:visited + { + color: #663974; + } + + h1 a, h2 a, h3 a, h4 a, h5 a, h6 a, + h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover, + h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited + { + text-decoration: none; /* no underline */ + color: #000000; + } + + /* Syntax Highlighting */ + .keyword { color: #0000AA; } + .identifier { color: #000000; } + .special { color: #707070; } + .preprocessor { color: #402080; } + .char { color: teal; } + .comment { color: #800000; } + .string { color: teal; } + .number { color: teal; } + .white_bkd { background-color: #E8FBE9; } + .dk_grey_bkd { background-color: #A0DAAC; } + + /* Copyright, Legal Notice */ + .copyright + { + color: #666666; + font-size: small; + } + + div div.legalnotice p + { + color: #666666; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + .programlisting, + .screen + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Blurbs */ + div.note, + div.tip, + div.important, + div.caution, + div.warning, + p.blurb + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc-main + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + div.informaltable table tr th, + div.table table tr th + { + background-color: #E3F9E4; + border: 1px solid #DCDCDC; + } + + /* Misc */ + span.highlight + { + color: #00A000; + } + } + + @media print + { + /* Links */ + a + { + color: black; + } + + a:visited + { + color: black; + } + + .spirit-nav + { + display: none; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid gray; + background-color: #FAFFFB; + } + + .programlisting, + .screen + { + border: 1px solid gray; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc-main + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + .informaltable table, + .table table + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + border-collapse: collapse; + background-color: #FAFFFB; + } + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + div.informaltable table tr th, + div.table table tr th + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + /* Misc */ + span.highlight + { + font-weight: bold; + } + } diff --git a/doc/html/images/blank.png b/doc/html/images/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..764bf4f0c3bb4a09960b04b6fa9c9024bca703bc GIT binary patch literal 374 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4kiW$2A`O3a~K#HSkfJR9T^xl_H+M9WMyDr z)b(_645^s&_M)R8g96V1g9H1Y`?|@Qa8+HmHda4(nQ?zM!!?FAj1kNm*b;aTNHv%; cj9>w=gf!;AOne?`3=9kmp00i_>zopr0Be8NW(e>Jab;j&;NV~o5MYpy zU{F+KFf?Rva$<;zVn|MA$j)XcE@r5%W@u?)XlW_#>0#*UDemd%nKFf8%9P?MQ>y38 zVVEwkZjIWyHF@jSt$X(}?A@Du?i|Cp zbLXyIW4Lzh+_h`h?%iX!chB(NJdh*`E$$X&!4}4&+z{J`|sZwzJC|^ z{$1kxcf;@BzyJTw@c+NS|Nj#IN5NBISn~R-X--a%afBxQ|J!3zMjr_SU zk_iHr)f*lf{$5^Qz}I)@3FlWvw(w~u=1P@VsTP+$RNGvxbHL-(%M6nc6`{zlU zjGQJeveps+!&Jb&mD)L@hA} z1_tL6*NBqf{Irtt#G+IN2MuLS&)mfHRNut(%;anZ6Fnn63k6F{eFF=914D)6qRirw zN{8Ia;*!i{z0_j8l+uFyyb`_S{M?DV6n8K%Fld2|%S_KpEGaEYWk@zRFt#waFg8d` zG)YZPF-fe)lBATd3a!N{b-$VA&f+n^|#(~yCI Ofx*+&&t;ucLK6T%G-N*j literal 0 HcmV?d00001 diff --git a/doc/html/images/draft.png b/doc/html/images/draft.png new file mode 100644 index 0000000000000000000000000000000000000000..0084708c9b8287c51efa6b40b8d492854191455e GIT binary patch literal 17454 zcmeAS@N?(olHy`uVBq!ia0y~yVCrFDVA{sP#K6Gdy&=krfq{V~-O<;Pfnj4m_n$;o z1_lKNPZ!6KiaBrZ-Y&bnV_It>gUxBbUGDq;8-IJzl^bZYNdFq&_HF%>I2sgw)Q7JN zaWX7AvyxSZ;a1dY28NFFCccr=a%;t-jiT=}Ffh!2v1?uK?S1dJ@0+Om6fE+-G`4(a z%(Bc`&m%QMr#-z^zJ*sSlffZoT1%K$@8gP{F?`Yf!JfU_`BK`3qL>MOAHOUUuyq5 zICVEaF;V1YxN#ua^vhOdFq+Vq?0GvRL+{f#=!FFy#0R*{}(!^yB1~4a?5`E z?UbRy5=I8a2^aW5^u37}`W2TjGSp4Hz^}Z7kwI?ag=~RK3=HueFQ#&2GBk+W3Eh$? zp3@Tc#)6IEL!;C!PA4gb2RHuzz5oC0=QrPGvHN5kEih*|u(tl+&-RwG)(LD37Kd%N zMDvt0Gu%m#yJe}B$j<_p{S z`X{h4{5g~DB<(Cw+xMN7;RAF1+$5DR-z%~i818?Zav?Qx(gpiRcNrOKI$Q3EVZQOhM844`yo-LdjblF7I)zQiNNHizIaZud+@W@y?<=U^W zU$0(1+TS^Wt%3QYA%E@JsNbJHIr;5&@?bs?_+v)A#4c^Nc6ly95Le=X|V>0PXf zybQayPnY^7_4SKxh75Ba^6n_@{HPUk^XF*WT5G`GDR} zzl@(#4J>tQQ=WWrZ!uwb)8F56Eo#5_i>KF5zFaGCiD85BJfU4Wr~5hg{<*(vUH2k| z<;;rfD> zIkUqavo}xovDT*S1F2Yf!)>R%t6w$93_Zu zpICRx(n*S8(T49WVo$b2x0o>G==Xw{ASF3EOF>L+kf`R~7O{gxzs}FM=X`GRdI@8K z@k+HXON4d-uB#!zHuxn?JubPWH|r@+J5E7(AvLs-6G5EOX1X zb$Sw&PTbd0Z5u2z8Ezaf@qKKuEq8a(tTKJhy$kOD*8BZq8IwcOCY{rt_pEzu`f%6o zmar?A%NI>zYdE`R9&m{<5EfJPbifU%&LGel$9@_j^m&oAXs3>`;Jd=DGM=uP)OzW1{Ci|pLnzvRAeyY}zj-|G0s_gYLCT%N4{`7-6% z!u^5@%dg&hwp{p+1sj8O)K1Hj%m3bU_sCcpa@pid^?p!dIJaltzEdi%Pc7NGZaM!X zkfXC(Oc-`3F8AMcD&*wLb+0$+So=9~7gafWFgGw?f9|~d)XU0w%QH`H(mCn3@%_Zh zO%vD}wyqP7+Hoo~d+qAOo66efgteG3todTN@aV;7lWG-~^P9IYG4Rz+z2LR7a$f4i z&F_0WCH{h(Y4c)si`bJdRg*67OMklfY^IYGgWShtkY#(9Wv*If_3YohGoH)`?&kTt zVEuggb?eOeb#--mr!T$szSHU@#qjR)r%y%UPTH?B#SfkF-@k9)x7zn#Ro{UM8(Fz| zdsLQR=Qg&N4Fy$A1*@mNb$#-s%E(@JLBGzVIca`U40(@MF-By^PE-ASIa?;ZZkCr6 zL*26tU#~}b+wQ$o_zYAP{y4}yH|hTD=an+Y3uPov*W7R{nl*u~;r)*r&z!R7KChhj zy#4O<+nvf^CW6Y$_)ilrteIK1I`{Uv*Uu`y{nCm)3#x_>Jok7J%duJhW*FGhHBBw| zCNg}!9QE3_2o#wW{Vn$vt6WbF^khCzuduLO>ttQNRwl!b?bZJ0cCd2F1|@wpnQFrD zr~C8Q3tcUIdK*h4LoP8a5LtXD({tIpWs}$#;;pAmxDXBD6qH=Ku+nP*NW36po{-h~ zVxg*H&M(!$p3D|{Sud1tl-l~L@`6hB<{MxCm`pWkP)@S_a`DX;unvng?RE?1p7R&J z#L(9o`0ntnWKiJowY1pnxck&Zk@tayN5+c1V3t4xf3NFhlhDw&N}!N>`FYFh^m)&H zFHg8o9diAv9w?k9Sky1Rqw;0l)l%92JIob%6;l7X?eu)Xa>U-=*Mr$ZZ1J5RfloeP zZZT;v`DtA{sm0Id%;(EF+*}Hd^UD4%Y4f}BwCLq7y=}G5E0-`XId*y7e3g=0kJf-} z^IRCr!{2QHV!m7u%%gpD8psrv4RTU`E?etn9W!LmOqe2_=X%NAO_ev{yGMqF_(_lp z67G9sR0uhPJXO}y(iT4ZJjkoxx?0>AZohl)`&gnOHp$lqo=ZMel1xbk(B=F^q;cWZR5TGh4aLR7FPbB8QvFGuC79rjxdll*1g4j5jAv&H1Ob zP*jmu!Aa$d)MXRP`tKhWw-^7K-4f=tk%ikK#^Z(Qu|k=)M2WUSnc2&3{wnKx+E^NS zUww2a^?lbJYJZ-^LpVrEj2ZA(&dL=YxUcw z-=7LLo^$=;JC*Z(NIXpD)IITXZAA8a-;ASHnG6pnUdZ-vnt%TJ@qatMOx##!wTE2@ z6q+1o+?}%5b}zEP@J9sd2G`7SYzN+!v`m%}dS*|&rn`9 zf8KM~K$ZV&@1zuY59rsMmRvSD$$sWk+`IfIm2sh=p`qv2^R&Ns$M!&Q@ty37wF^C8 z#4eb`_JDiwo$LT-XTeJhHkGxtrSmR$Y2N($*@E-!s_D@Y*`6Dz9m1`%Nz)MR(UO| z+V?`{thl(iXO-W+3q^mtuIc9VUPO`ifNHW&>~+_`375Ywnl3Fbc!@#g^roIU`@}hW z{RJ;E+)-Zs-pT1Ps2bLvHmB_NqCb92mb&TD6EFM#X%;{Ea+A)a`-Ab4{KtVa$1u@%i$V3l(R+{V!vbxv=n6W>$txkC)Vew7vlU-?ulq*u9u= zA#?F0whc3%eE&Y}>jk^44542NE0!?k=v=L;l6+eBZ$|2r-xgqjlRqIS2 z;Wzn0LF)uIf!36wSuJhOXFQoZPS~8!z5TAdZdOZMbc;#DjyLAZQ@4t8^0rI7V-pZh z_PK1bTl#yP-+YyY4+Ru?6|8oj&h+117nSY#qFH$fjr`SP(D_xIP|pM6=yq$YWXw8ND{XZ+89u6e)1oU@mKBa>lc z_lEwQmmPDn$YXh}TwPapZqu8~|6i9* z*{ySW*SfoLV!J`bpm|eo_5OYP>V8=s2zH9jPMtEl<(PHIC5AG$S1$e;PhDRj3@Jrjj46FUjNE`?vZgv^@>W$tzV$rmCzOD{28+Vb;P zrjXR@Ku>0mYi(amIC<4MG8r^)r`!(^l3FKli9tx*V!3CA#gREC4PRR4%s=;ePD`71 z$R!3o#T&cU?0dgF^V2UO3qB{Q1A#3kUsleGkBd8zY2oO>Y%#&$@4Y7`F&D4hTKk@n zp=s9how?EXKVLpJBYuBfYUH!`suOIqG8x(r?=b(?G=Z(a<%vmIV1OsI-Jp=GLUkU#gXzK>f|f_c}zTnlKo=>-7)>RrHp< z8iJP`VvZGlsbyl>=j5kscE*!gu(G!H?eBd$-j?qIG@t%9;iwTwtBcD1`}=$Tv*jOc zouoQiRla9SMWnp*j79FDfVxq_DtOw03p;eRnk zjK{K8 zU$StE$p*%D&bzPsbiA)w}59Y=epBMg~ zA;A&Wj(*BKPEs6+pIhR%UfY~c)fds+WWHzV-o^K&83isil+RZGV!f$&rpUF*dD>jB z-2?p(n>$H;(B9S}=AEc(J^g9rxoHpj6_-C0RphM@Nq5@+dEExJRqsW0md~F*KlKUo zaYqm4eQ%T&uJ??-c`2st_QcB{S|+gVkvRVG?c3a0%hu*U$vZYf=k%&or#AIG+XRws zoWQnc!?jcAlB{_x*KT#$YSN-T>vW!j-(gE9sSl|#$EQ!9zW0B}Nj;5A@ovR8`%h%< zaP?r`=X3eWw%qHboGi0@s?B|sn;&xi>HVX)98|zmTq(VK`}XbR`mpR+5my_@{IyeC zrtJ-Q!Tg`ik~f?q^T6WFS?8XAHsIm^6PcYGd%bdAyqTDx`Yw%5B7C5{zN`Fm*2{a1%mcw(XsX6o%$v$W-DzJ9bK z>UI47x`~%Pm6kB>U$ZsH$G)aDet(^A>8h45$xC;J2YvT0o_TH7frtSAWL_t!4|y`j zL8kvX{@JF!s%qE0?U9Riz222MOGzhsdh@mnJ>kSxnMGEfEhZ1s~L)`X6`V!uA}_x(^=`>ZJG;mNW{i*_xl9Uwhxarghb-dGqG&`?demi}$;q3`98(648`&wRG|^Yz8tU!}EG#|@7k zNPX8l=U6XCrosep`EjhUW=Dt4=}nol-fun|r7h2ql3Ciqy4t2Vg&~IP_3NGAlqbyj zcK5xn-}1%@Y)lj1)Kp9lD72dUYS+G}<$aGWe1ltdPvxxqB;vZ!{pq0Iwr6k zimX4e<=U^GKYt#3yH{mis$7WGfyG%&@h9}2ZpwOXF}o+o|FKw$iNKUKN2`AH>sL>> zYwe=bz3Td#m5;6(vFQcB_gbmk(>VF^4?#s<7E_+XKWpNGebOVp{rU69;b`XCsq>6H zTQj)BlFw|)(*9}q!N79ulwW^;n_KR62N}BcTa8_L?Dl6|sgZW}_V&{@oo4u9bN;b~ zU5#|y$zso02bM0heR#;~%%3ev%fEL{U~8IG`Dps|>84XBU;9;JH8u5TfvL`RMc)S( z-L{_iZ1eM((W}gw)(LD*lbx4^uj|)39ptyM<_Fg$7qh;{Hs_yzj{JK!%f#a$e!ceWZ9Rtj>;Hcf z^xNd-UFO(XrvAZoT53>4dgL^RkoJ==ZO*6a&fh=%Kvhi-liB3wKMi=a)0h3;H~n0C zc)9A6o3YoouDLSFu3)?V!wF|r#_LVrwN73a0?<;ik2-^(WFH=l{{{wiP0B3A!)7yq66yVmHOUNXDU$f~ZzWP@bq z-p@bx7RC|eqn$e5GcWf4$-BDvs|n}c>=u&^ zdkbaaV6`-@O#PjAz0@_3 zCGYdUwj5qv<99(3$7Qa5wmGfwHz;Cys^mk7AHA*a^sd-o?l z?-8kgZJy8R+;?=!+W@6IJKy}Sn$_aRHq}IcH9I#n^svF2m8M&-70Pkwa;m3?KCRTd zJ+eDmGEJ!h+%)AB|ysgBk+6IADhWgjs!{(JGOVD!iGX_`yd zY!$i`8tNG;dy=<)&GKGDQ1|`hf=O&iilVoFO_-*-#zE#k3R-HMlAxKpK6zE zou=%Ta%|VS?8pcEzSiztzg+UEAOBPnfr**3Zf$$JD=#(XYH6+2+?cyl^Nrr=-kw%z z>v&V~CG+{uF|!_T`&*&-^^1uwXfV4|aY^G2i^%TOp317Ku7y{2&ov4EUVFbZ_Dty3 z2`4in*QmCB-FCKW)6`vGcH~w_7xX>MQ_xF|)HB}7KlwoS^3yNHjIL`}cjwjW+fOzR z^QxC*p8oRH+OS+t{i+Azt_(H7jXOMimwjCosF(frXU(*&*ZJO`-Cij3^v7x0+HC># z=6>?W1NlBqc^j}I15^bbam|jMwselh)@Mpynkzqi6RJ3DaN@`-x#tg__)c39H|und zVdcE{?~K_O9hzezAp4SeSB#$a`e2cxpFe-r6H2HvIb5-O-1(Vnwg@#`J#UtIO zcqlXTx#^ZSk2g;5d|Ns1=@h}p^`W7nt)_Oas=P@IMS3k^|_p3cGJE564v1ZGmFpf-xvi$t~*z0Tec+7jg{Bq{)w{vS% zN&-dhZ$Em{>{;&ZQzjc$Pv>(m(^>s`mhaB~p7*u_)|v9rH-%J>EAHO4l$~YuLi>Ma zmcl-LHzx7A#oTQU|FqJ{uk+qT1BN?FOB!!j-mH%{_e2#|o!7?_RrgV!yJNcI3S0DqkiFUUGN?s`A&oZ=H5{R@WkqKNrgP$^E+5BKB$f zx&Mq@!<v^32&Rz^S#YKa7TWxrgfrGm0vfJq-?^~KV=zqUq1yRC_nXh)~wXKR`^Yh5y zaFV*wUODgny?fWpbzcn$QOSewzjHvhA zaJglln)8>Sh;~V4^@Sfb|CusWD@nVp+u0P-^^eQtIp^A~d~+^%t<*W4@_YL7<;xjv zcTTwQgKMhE26adk72jQIHTQ`Hd$_rp(29lkCpxR7a*If^mD{oTIX#wMGnwt%5sBc? zt51s}iv>OBR?fToj(e^f@86GdQ-UhzonE!Ja$YLWovYt+RZRA|doWig^%PE8Q+r?B z^`XI%%d5fW^%|Z(f8IO&=BeD%9vOc?o>;bO)xP)F^@XL{4u<;WZ`Cia2#PrE^m&oS zG+8(K9alEJPS2@#cWIr#R(32(+dXfMWZ~7Q(~Nzu&Dr9!UYLsS6w7teej_k2rJH6$ZidT*PrTL5u@e>Qf)%SW&Kb`vYMaiedckWMq?;0BF@9)3-@=Bf4 z(f8U@=*5pz9Ap!_VwGhZJ(?nr=3*1-0%ADpztr{$PnGouNHmt_pN^Ot8=%( z9o{$n*P{A7=Pk?h_0+xV-~ZOm&8dD$>P(#tVO}SfJ$;|X=#g=!+e_-k>TS8#-wS1d zipgE(%ROI2>pU+z^I7Nef8Wan{JpyaJehZ=tkvyuy2iA2XJ1Hld2hw!3+7Sh)=j&5 zH8j+7<=(HgiT)g!3DcLPYM$Qo)!KV|u6FOK?SImQe#M=Z*s;~@>VD-v594_@gh##p z+U|Ese!pQ!?HkQ75!XYUdncGRt$ok*`>?%K!u>fiRyRxU_U}J_dEI>9%M;=bg#Wnd zaOF+?tzTt}Ca2DPQ@3@J&#b!7(jFNJ!e=~{m4p~JtvL~8eSY&CN0sPoU0L%_t=FRJ zX73LcFL>i`c2Ue9!GmjekD=|23msudAtrtFa4_BynEeg&?I*Gem^H>>7=RzcKP{j*RGYuUjO>_xU7)W4Y8>vO_L<#+8oU)BNjy^eQhk5 zy7N`#y!ONizB^Jk-?i@buDn$L%TPsr75_p4yc2Ir@|1wIomdIG&X2{z6g}5>rj?Ocp&~dw+fWp4ZK1g2F?m z#`&H9{O8xNT|alUE@)%Bws=xo^0iyra)0mZUp}wez3TMxOfP-=9>dVkqXL&yOdhb< z+ZVX~IusWl|8&alwfWDjKihcEp8CdS*Vnf@L=H0*3P}~TKFr&pc)Rn+1?95oI;Z`X zPc}^ZoKUrcFAlSDpGEe?%g9nkpx6#i8?} z@1|urac951eLGr8@$K&8vjg)EnAdG7n7=Jo*e}EI{O8lBPp^x9=n@)Qv}7v3iirS& zee8~AovpWi={ZgK`Eu{|%Td|>w)f6BGbesvZi}9K{`u*ro4&@fC@oJbjotow&b6rD z7Va+DXKhRb*zA*ccs^*EmV03Reh&X{-|tob-t}b5VeU(sY%NDLBYs5AXql#Ca_q$A z`0U)Cjn~e7&gq%?ymFS>+OIa}4~8-HKepg$-k*7w0n~EIew#ME?%Be|100!u4rDt; zXRG#X)|t#O;s2g{-OhFWI^B~3Gb}TLKHV-)*q)o+v-0(=*Q+b0KCg_N7JGf|{wddH zwXiuUE%_+Bo>SK|=6dP8=bNs7S?*uo`7qTqFi<2Y)O)6O=G&KiM-6x)r@h@iZ(7o> z_rJg9PuaTd{qNZN6vl6@i?u$g)^o1iI&H1lCY|aXey$~w`+o0>xBn0jdi7-q*Usk}1t~2icF*+}KJ8I^X%+W>&2+;L``-WFC*O83zT(gI z`oGuf&d-^){Y8zP_0P)xUteFZJ1*K#o47-I{)Dd=@|e#@%}$MsoR%7y7WwSeqti2X z`s7$kUiteaG-XEla?vF`u{*NlU;mD);RCC!^71<&er~mcdheZe)(ld(Toe% zPinOf|5`lzf$tod8c!3aL~kp%o9maz^`d{tys{aWgJ!+AS~9&h`C7b} z-KGhb8}eIB?(`R(zEco;{r0-ZQ=8UgO0|nmY4zDH_tET_MWufVzr{_qyuVi&YFa1Q zSv@x`0ZruP%)9XFy<;!m@4c!s%VK?2@4qbIr&qc&M#!R6x1JX<`+Pj`> zGJP=NmrZx#Za;nC$qOI#>9@M(SiD?yHrkIbwqBD#-u0J9tNpp}Py33e{GPSND>d?2 zN*KQp;# zzhc+EW96~@M);gLJv(F68|O@W`sVfe#apNG1`AjCH{5vh;3k(kA81x4xo5J^q@|at z=T8e;cl-F9`MF#Uf|uAGomTIkowRQM!zqhatkP1?-neAOva`|!dFK8RHa#tI7CX~9 zUz)U)Jw3szE^qy;Qtr56?{?OXP+91g?9H>cPnJ%S{4y;zV@}9{Pajj?-(JQPc=PFEvF#RD<|UaI8R^bFkf!!N zCGy#m&E23n#^4dJ#g^;Kb@x4A+}2m)zfpSa`S8pxKh3VLMFl(dR$edF+-rGY+qb_5 zjxLvY`mfC}E!FRInwqBQB9dg<%+%npK=Iu#e@Z&XXV`z+FC%eB(j-M4P1NU+`7!>E3#@>5gGzKf@7uGa6| zHQ!@LR&BV~#mBrmCS5uF{e;I0>9e2rsM)9Nu-<4Cl@j?Z<-6h1DO2LA8q;5`wC^*U`T?H(KbI zUeT#1v$SOr|6F^xT)^r?!_-SPV)Bl+x8>fp+LQ2!Q#bX?tO?VM7YEhWw-_$d;0mAb zx@%psuGj{*Q~k4BCSK@|wEwlM?(n7`p0^jQUj4P!f42FD4O8ZySZOu?yvi5mHCwgY z7BJumR7>`ZbJyJbx~nqw;K_{I*Y9lCyI^C4&^3yL%!1YD|j zP;Y37OTL+!+H=wuJW7TpG^Ec15_1!z0Sz@RD=KZ-OStHYV53e+L+b8fL5}s zx&LmJ&S~bpQf|;x!McCHw5#7VGFzScTou2ht!%~x&iVX*dlMzDxjV&Pch8pGt+x7{ z%)I!QPm+ZTWZ0`x-naG#z6&|u{?F}t>GRK(PhCIRlnyrowRc>JW^$!s%!KTD?f>8mW6os4(hIq<*xVJZLAF2~6_@~yJ6 zfL~tbdyr8RyLF<=OHCDW*{jOj`=oAlE{)82DznP)S%7uv{}rpW!YyqLZc;B|jJh|}w?=OZ4ws@jGSGs23HR;vaUsjataO;QV%^7cgz1)_x`P#Y9H7mSa z|D9TQPSPG-=zOXUr~TK}xSdvu$QOnpK*sHw@LxRJ0y7MW0*0r`)s&su->)qoyzQ~L6@Fx?@>QK z=O%cj;*M!vq1D`=zv3J}+&uC%ef(Ct%%7Ae9Hkk09n>AWc5t7r=*}aXUAA8N;yuA# z=tj|ut3PY@J-w)C`_SEPAxlK(!*{wTAMaR~y>!a;Iez(fZdW>KFP*df=KZ|NSjpt+ z{+vOlPCt9N$?*BtNO9?VuipOe5|TU0cxb_-d-JYb&b?h_TcNPDFkhZic5P}x&CBEo zcP~7#->$VufBNa~-M@o>eP_$*n9#@c`SNz_5U2f{OIDvO52!lv*=D+Fa!^V;=NoV% z*8DS*=eZ3G4-N0gwi-OX$N8oD{O3QPJ{8?Co-%D$q}$Qy|B9DR+0w1QHeKlUKcn3m zT{h?K|GF*t7%9-fGPT5I#q#~-Po#dizgJszdef9^#*w|c+&g61wr#n-ci+B!w;j^< z|KHVM5$NgOQuRw(<;(YV%n?!>uHIMrT~#~X@R;Z8nJoJa(`GGuYNcZGKxS%5Nz>KK z)=|>M9|GS^U8fxBw_wuyf14C%RhevPPpqh{oVeaI;{dypm0M4B{N`)>_Us98w%&Lq z=(NEOpIGnLHr-Re>rDDo=*^^g9w=|vtq zoV*oI9>=?@X0`BTM&4IlspD>U`o@nBY$=AIdmGB)Qo^W2Wx?yeghbXvSb zUpp%!fxG3)ITg!yvdgANPZK?<7-%#Jzu(?3K+~9$ zq^eebeEzyKckNdLp3gSkMcPYKa_s+YEChF6_f}V*$*kv``~2tU&zo0I%-x>C6XUmJ z!o!bCRdo-^Zt%=dU~4Ji`Zo3QJRz&on{3YeFAok0{4UCwliZ`@DStfhlGUWM0iGEO zLMtvr+v1S^z7H(#QcA$M}~r2ONrH^^O^ppC4nNYfgzz= zFSpdCzvPLJI-g=!J!=_5y`zv+2bbbpk;-M|vDd%vy)Isr;M=#nMelUbts|E_UX-hB z*m})KZr_%9y3%WR{EeP`!6Ap^<&`6m{*y2G#k_AwTl@BRT-TeWKjJ>yO}OCD!ts)& zb>;H>`elxPs9m2Pp)I7fNPF?@^=@w9POJnK2`c0EB%+oo2 z=1Itwr6=~q-QRlU=BwLEvs>5}xvI`xBk?Lzs7m;K+NM^PZNDz)`8hEgDlZA%mg_h9 z!o&&lKdP=;8e4Odx3`5Y$<0GOZ?&C~kd@!{wdt?k3nr?V2;E_0otQ0joPIeR zda@;2#iT)5c}ah2yrr)bvxSAzuYzxrE~}U@2wZX(srQ?Ffnfp1%fnrk%RMs~1X{in z9-Rr2)ZuvP+^q`|+u`ORe|OU5qJ0nB%AK5;4_K$YmOk)JW%=t}(Gk!$ zq}RFcS-Um%y6(pq(3*zIdHPqkweO#xfAH1IZMjdMZqoVuU5jCZdwWEas^|xczH7HY zi$6EA4>gX`_|0seIM1Z~v6E zdn#0!cL5Sz&y4P)qFLwF423ytpzk0cA zopSy>u9=rz1K%X|Ff#1%QeTpK_sY+jX{w>o_s`wka?LdmylP|1eBBe73>=yh+aDP4 z)ZXuZyyK0-ChJR;c0A6J(<c z{a-AnKL6NWMwx5p=2dN~z45f@gPR*06 zyml*5LT`F^j(nNPXPbDv>6x=qW`?QorXDPs^?4J6%!Ryp<)3X%>!}|1$@sc`iCmkb z)UDUM`ckINs>^5ikRs2&yK>&`ZBuJ*{fgVBUOnmj=NhZIJ%)xnwfdI2i)H`Cy{NG> z_g#Ddrv%dS%m|<<{ zWs^;ds$N$IcFkd9SiXqwWhQ7@UdQwICj*K@LsKL3YW2NXW9)UGr%t@gASCvlxvyp4 zL?7np?6q4Bb(ZiM+ppca?7pA|jPkw&>L7}Lmh(}?3TQ1b=W>4ID?NYFA{E7Lqo?EV(6IO5jcg3o# z&+GE9r7|9b&%uZeJ`c&(@_dOcJ^7tn1@+`s>m=Qxf8Wep+3y}QQIkJ-c1#ed7TT>a_Y?^~`#g@=ZM^4$Ar z;`gVfzc;GRoVx0D)Ux*J2g=Idmrrona!t(D(U19nU#`84_MU4Og06UJnfn&o-h9(9 zayj<8XVhw4zdh$Rtp#@IGr|nG~w|6pk=33w!4&GFKs+r zG;7(u_o}=40{l1YaXTb!tDo@G@5LgGQ=6u+9(ma8C3Sh$vWb^hKap5HVX^q>iMQEL zX1dBtHnimY5&3*qQ*E~Uu??xqc(zF=r(7vNd5(c^#^o!Q87^&js(hy02{axgA$)S@ zX{T8ySFf^~fBv!wt99Au2FtU*G8s5;tSLMb?*mxtpUh;~E&L+$srACEV$xH8 zB=kh`weU^2TzlW!O-^O``RAWsmIOU9X_(9LamA-87ouJ-(ok6#tYke!)b(L?>m;jt zm62a2GTsn>e_qpn@13HOBS9rF-VgMa_*nH8%Rre0nLTHR=7 z_G#@zf6IOGtJh^qvfqo@Q0wQnJUCF~iAlqZ${MGis~7f9xbW(|&h8$uALlYHdo0`L z@R_|k`^Ti=$ImL8$|(N5G85i>+cc4T+GQizcV9#E1dWzIeednZ+%b82y71yV=S+P! z=lDE(sk&zC^wX|pj-S5>ZRf81x249{kGW&QZ+2nMx1OP)LR#~RqOxtz7hf-pdc8@f zcF&Q$--X}Ac>ipg!zLho++S7bmi9@%^_I3g%{ldA&Pf;F^FDYGV>ij;1q0KQlIx|% zB-WPlJfC9lj`zWdIkx>CFA{2=Z;7!v|5?H*>hImHZu`>iNFP|Z!?Lfbh0iDI&fnC| zt>3`>z`;7=E0(`;{?0 z+VypbRp#2-Ifo7V9vkpf&O3hDQEgh)uGd!b*SB9Y^Ig2PFZY1_0mnPv&wMT4Cd&EN z<+91Vdv5E~tJegIxJFK!_v+=c%u}0E)<_=+dsp$RLh9+XE=_r5u(s~%+W{`)lB6G;|FKLzs@&uU>4=$!AZw4PJ;_Mv$u9)7?KA9}hjBte-x+<(pTwZvK0l^LhJgFPro}-Z5qE#z;^rlVQ=PSk<>66?_gw zw<-;FPj9>vcX@65>r5djhn#&pne}_`sFWChM~W@azufm;_;hBrE+?;o)BN@=*W>bp ztTyagclTTJ`Oh}K!CQ5k^lQJi$ZQ7)B_ub5=kB#RPZ+~K9 zYSJ)cFMsBxG!Uh%9=$*QhJ1^eV`Wsd*o z&itC|7wpX3ac95ttjZT#EYH8poTZd6A6+x+vWiK=kH6YWcCTC9<~RG=E*s3^ z?TIs%oxIArw`w{_LF|dCL9y3=z7U!0yTtQFg~k2m9ErBdd2{tYeoDFd+{JGFgbNIh zrkBS)&s^-jbJ^Bun=2k)G&yVH%Xj|Xi{EyqH*xge`4JK*Qnb4IX9DAc2R;3<_Tsho zf4>ktemLdm#KS(lpC`P`PlkH=k0Vm$EfPxg(;bL^&oC#6>BAMdN$!U0 zVfo&3^^eOytxTD1=GOKC!VC-Uy|s8|y}Uh9VY#y6>$bTuUSdAhJ4F~C-1@B-|LW!A zf*m=ajYBm*QZ)On&zbjpW|fr?pL3N2Th$)M13S-OKW+4`mSvOboYh++YRnlA?9?~k zs<6EOfW+kIJ14()y8m702ouBheYY#Se!hIN^VSWQ?A*0aqd6J!{%){U`FuI^a@6z6 zcPYAJw)Yqw+&N!u5$wNQ_k3~knP1=U|9kpm9RtIwX%oV(TwbYt`qIgX(w9v>`m!*z z=hd2AcAsY8`QmH-Kb!M1-dqfPcLVJwUS2ur+s3cgXFi{qB*h@JD}Tb|IewE2)lP4k z>bhZT*}U|wOooCN?`C=wS=nB@wMZk(&-=8N&e3&h3=hsJpHD5aGK|Vj?pb~Hl3yMt z!vZ<(%%i*3h@?ht`^P(fS?9w%hJvRb1^uq2E_Lyn5mzs}FP`DSg;kjz$M#NMxOJN2 z`>EF-p7CNR$aw2KbB^D!UtY6hk24(5W&iCn@p5Lw{coz9FV-w)I3UWdxc0=$kTp8X zQde$SJ)4nX2WO_M-~0K7$4>IytLbMrAes(R@Hcwr%H^xSUSnW*XtYGsa&P+U-Mceo zm>IUqv~N*bUVb`Cn|tH6m=@Ith6fXVPY8SCzAakYJF#sy;{jcL#kDv3bLL;$KVQX! z!QzSb649?;_|~p(=FDU$IFan3{pw}x#LEk=@0sbBwv~~Ad%xn^7s|K!v)`UFUh`xM zpOX|r%tyIPU32bnu51pEJ0fw|oQWZZQ}B{jh~H-Qr&5nC*3~o5om0-qAkgR(#rjft zcZ}YY!v2XjUwoaqWpXzIgUgNyVP7V?`rO+)Rs7`VJ15`WXJ8QgHSyGr@|Kv|HIe%_ zYA`&w#nyj?!Sd{m?|Xmko4+jctmu|&mGgG*l4oeRrLsiy@4bnU`+s=pO?qxAe2L+~ zg|z0$J=Mn-zyCc|_|mngU%MC&?9@#cIQ*r0@@3G*wWki-e_3CP6=|Iu&BV~rd%K1S zDzo$b@2TPw_a2)O&%m&K+xw$S=iQs2^5vJgJ7`B7$mDC^6xaT_e)-9leZ27R(i_KE7-~9R9Q5*IzxMs_ubUZ5Ljpy%lrcB(3$|`i zTFyLa>&4f!T=8ot789}R7X+<4lI54?Fe*Kdz{MVwgbFY{BnaQnuJ!=|B z?LClM_NdpNf4+ILUWYw6$c?$dexrTj$;|ENo_{{I*+k4W@Ji|1CqWDi{zpOaSGGJi zI-GNEYGmy7oNK%cac>oth+4iqWWaOSz#>vY_jsm6@{8AO4C}uMUh0|?moCw^?|p1( zN%q>=%M#6`7;0``E}k~0uIJCyUF(WV4=&5hc*WMh@J-}W*PObJ+bw#hC$+FO7?g=! z>YB6f^3x*A`RCW&uBuXIU|>EAIu~HwvaNbuO>=iKD)jsX1ycSqvxQTGLPIwOn=`O% zK0P7q$rs*V`^slu0Iic_5V#cQ95wOseW|vC4{f#tostL^VU@khAaH5l{GCs}EN@HP z5u>+GEJkx_k6~)$wA7P_G8i~A?}K8Ae_Bh~4%r!o%Rpm43{1CcJ+%K@-YvZwS9B}b z$==?6@&yKgI4;GtHqW2JRT6F6 za__2b*&4>St9wyFsV~C;W+9%;(iwB6Nmb2K+itoAv;uhI1%?efO`M}-6_(rf7HKb? zH*emJf5Hq&3+CECTKsAM|KI!n>8%6pFIo5c!|c>a7Z?gyPKI4lI{EeTKcQWjvo`76 zjT2`0u;GYv6szR-yxV3Gpz*3zt8UDdW>_?-4&+^3-D`|Rx5}M1Kj30mRMasc%=5{X z{Vmgk*JV6sYq+6u&*EF(bvq-=!kw8?^0g`ZvNMFF7?et;ctyS0GEZ$G7tXF&lWN=T<3UM zf7539%yu@0J%{IfslSm`7o}7)OHD|MVZ(w+|M+KLxg6v?`2s^jImgTIOwUag-(hH2 zZ*b@DPJ_qyE}Klez|gQ>;8OgjxtAlSMP|Qz%EnOBI^kd6^*PhZyd}Cf;o02#20>cCer(fy2Ph<*7F&NV8P0kFUn@;L4th^6Y4IsfkVns;8Oo>70{rM z1)o#Z)B|9_g#wqdSx>**q~n>vU?JjktC7Jnc3Ns^sEP@L4A=4m%g68c=(z18K5z(2g*)X6Y`6qgsjegp75QS zp+jC#_S|yIy((L-S^d#vWJq%JVE?KI^1}ghj+YmvfwkX%yy8^uo_+f!U0`T<|JOc2 YsPxZ;53A2HFfcH9y85}Sb4q9e0Fi|iga7~l literal 0 HcmV?d00001 diff --git a/doc/html/images/home.png b/doc/html/images/home.png new file mode 100644 index 0000000000000000000000000000000000000000..5584aacb097a80e66a5320312b6e4eb017af1a06 GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&Dfg?(A@OuseF>a6(*+nzF*onKLh6zO-%YmOy{sw6wJU|Nk%gvq74Hfq|za z$S?Rm0x$^OKX;CSfq}EYBeIx*fm;ZK886+f`@_J%pjzS@Q4*Y=R#Ki=l*-_nm|T>f zo0^iDsNj}alvU8YOY t9}F9JU6`43jMG5vNQA&8NcoN_f;wr$vARr(hAt9lu zscC6x>EvV>6{VS+EaBwj6ciMco$ZvI98_E!l$@NLot<4>UER|o(bHqOcQ41TYc{y!?kM?_wFg)yJvXsp5^oB z9Pi&Vyniq7|3Ab3{~Z7S3p{_W`TV)z`}cpO z$(;G%_wGG* z?AW<;=dNA5cJJQ3=g*(NfB*jb_wWDz|6hCQ@I3|w2F4_BcNgdM3%p4T42R|DNig) zWpL0?*7VFxOi%SqOwUZtRxr^s(z8&owA44S&^IttNG{4OE~#|Ltt>9dOx8;+)=McZ z$j>X$OU}=oxJz*d0|SE=*tpE}yu^~yqEv=t literal 0 HcmV?d00001 diff --git a/doc/html/images/next.png b/doc/html/images/next.png new file mode 100644 index 0000000000000000000000000000000000000000..59800b4e87f60c0e3383ede2b384b9be0f5ffe8d GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&Dfg?(8r&Hr}>%OQ656nzF)*4nJa0`Jj)#l9-t%+}PK^d+g590~2^trx_V+aGYt)W#Kgko@Q{~>i6>w}LxPb)_bi1gN;4a>^d{wcuv&t)U99M06BF~bt=lC3t1z!y3OU-_; z>3=1k>J3(3i_72APIz-IDqpqc+E%+vGv;(%KfZ!%@4A+C&xmZ75-RagX8L}A{%x+r zX<~gz))PX{awr=ezabJ<%O$qq%HpE?3}IarYhrI#g}e)4`)(-lYr?KO{@fm?UzpsD z&F7x?_G;CcbIZ>^o0GCAMe@{JfwtZgS9s0dn=t$|`IrrC3yU6#%a-U6G$wZz0 z>m`@($9HNPdGJ4#pEvb;3eT@>Ck6%v=MvY5lHmNblJdl&R0anPWlhiA#Pn3(#PrPM zYy}fNBRvZROG|wN3w;Aah2)~l;*v^-+{)sT%w)aPV!f2og8aM^z2yAdiMtecFfcG^ zfsM;d&r2*RElOoDPD(L1F;6y4H8Hg?FgGwTOER!DNJ%kHHBU4$OExhPxjgw70|Nse jNLN5&dMbmFNrjP#wt==mQ8cF^C=xwg{an^LB{Ts5w*0vf literal 0 HcmV?d00001 diff --git a/doc/html/images/prev.png b/doc/html/images/prev.png new file mode 100644 index 0000000000000000000000000000000000000000..d88a40f923e3c554125f01cd366707c60cfcad04 GIT binary patch literal 334 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&DdqOG`60Hr}>%%ZlYo1O0u~loc*tzSP~>;p||S5Et|R|Noh1c$yg)73T~N2spa`a*~JRJ5eh~I1}5!gYtAz;Fo=OPI2WZRmSpDVDTHL^rZN~B=o=X8 z8<-ql-^0nkz!2u?;uumfC;0|1OPoRyGxLNShYX~Tl_Wf9G1_imu)%RA9}mw<0X2^e zQioc&m}WXSvRw^OFi2qFa&lm1W^U?K=~^Ook|m{hVvche^Q6-g?(V)Vn8U=toEqFE UkjD9gfq{X+)78&qol`;+00?PtqyPW_ literal 0 HcmV?d00001 diff --git a/doc/html/images/stable_vector.png b/doc/html/images/stable_vector.png new file mode 100644 index 0000000000000000000000000000000000000000..26af7af6d86dbb3d2e843003ef8d5f3807fc92e8 GIT binary patch literal 7163 zcmeAS@N?(olHy`uVBq!ia0y~yV4BCk!0?-cje&vT@P#SC3=9mM1s;*b3=G`DAk4@x zYmNj10|QICqpu?a!^Xav-+_}E7#I|iJ%W507^+km7#f-x7=Hd|U}$*Bz))(y!0;-8 zfx&791A}<}r1+z53=GnRo-U3d6}R3TG-PC8;9yp`ZoefeNq#~tGXq1adczF2<^++R zra%KOw}ToItcw#wE-*8&2%OFk;E_LY;)I11$6}~_o2bOx8M1K<3Jq@VHttZx5S@&% z3=RxsuOk>37#I>J?Ek7$ChGc#li`38qlwj3JD-CEGiN!(*%`?EF?lr~WYgt$E9yNy zpVyEe(X<U+$ zgG!88^EWu{960!5%ZZGbeu(86k;YsZpa=#f^bJiHUrxGcAqy(}dYUe7N)ri?hFSj2 z3lu3}nQQvU9^Y;Sj}JLX))Gbr#v?!KO-g&dX~8u#U37b+v4EL@W5Gqi^H2|fO=<#1 zM#EhzF_0%Dp5)th$GT3eU}D(d!2r&lhnW@pH%~UwbzHY^;k)+_#rU>-dF{b9JJ5iO zEm_hu=yc``I|19MZ#?p#C{>oj2fE7Ul^44kTvhHo}+{(XNuV+MnLOSXkZ;GvP z6dSKC)FIOfS5B;SuRgsvq2%mUP=b1TC*ZsM)>lUY9pWKM1n*@?teaW3#n5Gc--V2W zpv;(IX&zPH%ap|Ez|cGIvE?DI*$*!$IO`R-ou45C_U!e(y9N5sJ8b6*FJrTmaXbG_ zW)~!Z9^O(Q_13VDDJz8GMbcvBlOX>wdA-(2IxYC+Q@hCC#R(snAZ1w-FH6l#k@(~y zlf!*Y7yFKb+?KH7O6Ha;)?93Skkrs(CgUb83o-+oh+eM?bjXJ|`r^EY8WOB2ODA45 zF$E`!wYS|ES3=yd*!EbU!K^;F%jdvmZsC&#rxs9|@Kz9>7g!gU-qBdV4N5C*&olfB zMS7YpGS!1~W7PCscu5fUZgGOhgelkDxc`7+;9!QWCD#dP3G>YM$i*`jTyD~nz)pO4 zqe4b^cbgi-NRC%Wd($p~^=L@29^U%c+UkOl34;SeubEAIA)D;kmcY|Y|?Ey+e;zptBn z|Kg|Y7odR6t>By7V?Ik0o+Zla+}Y#UtRZePI5T1K%sdgEr+t^eK_k-BSH%ZS28nT< z{b|Pn9afuI%-RNa)fJY-i{~jbL!x3v>XD0Q%(&dFHNk$Jc!^O?_i&pW#9V>%8H;BY zi0~ZW0x2`!GW1XLJS+^+DUo{MqK_F@Tal_E*tM)vu4OMyz4U+`QlK7^%rW`g+q7_! z9MsJUuhw5I%K5<90IpCPddxuu_bzErF!W4IUYuY6DWmy>95UDEYza5#YIC-d1IspD z{8d=N4A#eY_};CI{Cp9frC(sh#@7cY7$H`^J=@z9XaM!);;&B-$v{6JlnhKvzz$u@ z?+!1is|yz=i14g3u?5SpF8=!T12hr5z1!Oq=untwJL?-b)E0kzq@lnD@%onUW+2BW zLUgS)M>4MzWZte*iQojs<@WmcLs*{926;6ggby6ffd*0aeD%;YfA0<`)>yxS$b>EP zWZ=nq?GaGe>8=2gtc$;XfO|+_%^i2+Ga3@QHy~0^PiLf8X+RUo$5Rz1%Dqhs?@a`! zv7V+zjd(Zf$)(SCQ4$ApV5`8lYe5@^8H z<~7sg*1~1>&?IrnX0c?7NY9sZ*TBvd35Yt@Q?`O#3=%ROVFwmVri<___X8J72_ifp zlE$|jm+3=wpEOx4nJmI{obL)mH;>CslUt5*7LbrojEL+{n-OSm!`f?c?^SRfOVFF{ zc6wzaGbDzYW~Q1r_cTq6gI1M{TVJ2NSd^6j$zSY=X%c5OpyA8q##sCM@I^*9nh?_~WTWtQ_2bJJVO(yWKq7RW=> zvQ^m=Xdd{s!|kBP0`G%1vz9@kvGjum*vRJ@{y8E&O^$Q_LBtcbtdq5a7`WJWEy$kB zFTvrrrAA8kF|2iQi&>g=aYNqA!Yv9AyRPk2hE~5@+Cio1g7rL*q@1wDPfiYI9;&<7 zR=^>%R{D1|ZyN%V_709$u)S0y}R=71t5I?*Po0puVqx7Y6`@tal#e>xwFDx zy$f$=$jE+O!UM^h4BE#p9P-q{O+Td9Y9IRG`7F4w<(#;NWiaKVH6t zN0}dLu~g6E&Qg({vJ=qcS1~nmF|*GRNH(~nxUf&{7|2ja*nMca80h~CD!22X#Vil^ zgBkZE-!1@~%q9n_+jt-@?iGHKp(Mk)xH4snGN?q>keDa?>|#+*2{?59t;{6cg`a~Q z4M~eztj{oCtdoFdO%tCPi#tK}0@P}&gpwmZo zR6lMe(=Kkn~1f88{S+Sap;+3mLY4oKe3jM3-`JGMAM<%xJ!_>#qyX`tll z@V@VJLasZHIW$m1iWYMgyeKtrd))KyWsS)hcaVi#ZO+Flw;1=zgJXR1vDQNwipE@S zpU-E+LAoMqcGYh=a~PC~j+onI-sG0_EpgtwL9%!I#S&0)ka5$<=yA`qLKCZ3oS@p= z>XB!&Q)8U-_r(cY7MjdCT(V_?9P8qr2_igSE2MpyXMm!qY|6JB8h6YzAj@Pko57*vGUlEsWS#?17 zpMj*_%QBOB?#Jd{TYS0Y3*+LacQP!^Z+(-9`N$*Spj>yPxFi=;#DL=&lptP^vWMnNRAvqqb zDPwoa15l*h5Ilb|4${a5MV0}V+im$Tpt3IsWX)W#HTS_fG$eHIvw^DV4w;WKvTs2t z*knE|$^3K!HAa*dJ+!onf;2uMc3mtxbpX`zDpa1gcrmzY6*~hmvnkNvmYk#ngMfq1 z;;C0OB>W2PZf%sPV>K>{Yuo7lxKgC2Y=_&yg8tVJqs}pc2Eo*1Sr2Q@bC*_I{1Ke? zZppJcZ!NYJdL*ULFvHEsO*VH%-=1?vp%KNpII~`)=h)W=%nXc2Or+jIt%Nqx8bEbd zoA2StQ{)b2_!pYYb3d421B%93-`o#o#9Rg?!WSJ#86Tt%)Fn8OC(8|rSe{SY=N(e_RQ2xQ2x9@5Kow>)QFi(sC0QCv4en!Q}=D!lsK` z?77??R~3L-FtLvCNGh;fqQOS&3xsH#}- z*H+)f2^CEjE982?edo*nH6(hU2RitJN*8QFihWG#kkwVYAiY)cSq-;>ITwGlkvhLP z;m48B8WO($7eBqDA;AU8gIJ>oyLniX09^xTkh-8FbxGxni4z4|K?9r@Lk!M5t~Tj& zcZ-uddmfbhr}ZyR_`ux2kR*9Zvh9i&`)oNU$^0!v(sCbdZgoi7eeBV%ODtOQLKYOo z=SzC>KQPDNS{7y{t1It*&;hJ3la*cT>vV4KJofT znM-uO?d@wiD0*Ju>yjhaGi>5Z*2QxtKuW>|rLwN)9jAasfrJ=X1i1Gai?7_f{^A*<66s&y z#B`!0_Ty9*Ty7uuDa4m6oouFYWkt!AVv!ye1_1}3X2r$*VKT~#9prnTU#wUb znrb_1ncKktzvD}C?lmqgcd8KSX*$RS8Vy}l3ogx57#BXC3bHke7gUJ1S%V6R#xp4= zcAs>2*J;a7w30f%_@m9O7c#7iU(VRG#rBqiEbC!j29^sQ5+9G4wl?XQ&6)|SN~{dq#+UYu_woFVH>#MJvgJUFgMO=TlbaOt>AE< z0;-u-oONwkcLCBq0+m-FZ?J;<0T05{F71A3e(QqFzK=Fi+Yj5%bAMbR!t=GnXU)wk zWrs8FNwPMB+PV|=ubw+ExEka-SP6gOWrYH0jGb{Qg93wfInrn~mr6f)663-I*^f)Y z^@~cXl0fAvq+*zK`Fh4aN!BYY42&jLkA{3fO2@K7K`f`Kr>AGJqA}9}c;);OR5^dv zSfCEd7Nm^G{*dQzYle-DK$`m^7o-?iE?}*$4H$05>gRml&sYqq<2+scT-G@yGywpx CFT|e! literal 0 HcmV?d00001 diff --git a/doc/html/images/tip.png b/doc/html/images/tip.png new file mode 100644 index 0000000000000000000000000000000000000000..5c4aab3bb3543191c360387c4af9a3cbaa051345 GIT binary patch literal 449 zcmeAS@N?(olHy`uVBq!ia0y~yV31^BV36QoU|?X-y2mNSz`($iDJ87yAgr${wU6ATeb^ycE^w7cIp z?_W?xU6%d(bb~@Shbi-aG=ETBbm~(ogOmrW&bwBIxdt+K+A3yD;V_t}R>0LF5GN)x zed{W(mq$!1ciVpPy1}W+9bm)Xrgda~bSbG?a3DdjluYV+O9SdLnMpASqX+9EZY3c7C@7#N&OTq83NAIrA4U>si~GJ7Ut&0mS)MRMrP)TsYwQg=9VeOrfC+2Nk)mu rLdL(;85kJ&K)M1F(^DCYOe>5`v<1B4~iR4S3j3^P6tl1hi%%HopDWWCg4y_C{| z{JavqiARt`YJFJnVhX)qGzOMplv!L->5yAl zT#}irms+fsQd*FoSE84kpF44v;tmD|1}(60ndy0nC8b5F42emG<`xDZ$;L?r7Ky3J=GDKJX@I;2(iM=Hp2}coT4AYeplx7Y_5oxZgQu&X%Q~lo FCIGT9P(J_w literal 0 HcmV?d00001 diff --git a/doc/html/images/up.png b/doc/html/images/up.png new file mode 100644 index 0000000000000000000000000000000000000000..17d9c3ec491ae1ba22188ce85985623c92ffa9be GIT binary patch literal 370 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?X- z3h)VW6&DdqOG|Thu-mqE%ZlYoyE{8BU%nLR@2jS)FmvY2qel)W#Kk;%^zi@x|I?Un z*fKCM@RbDl1^-6|46X<6oM2#J;4JWnEM{Qf76M_$OLy!3FfcHvmbgZg1m~xflqVLY zGWaGY7v<-srer26xMdclmgg5`7c2NiC>R+Sn6#IzInThrAO_OlT$Gwvl9`{U5R#dj z%3x@qZ(yu%U~+tY4<`cyLy@P8V@SoEspmFwHW&!FJyeg_(XezvV9WvAI|r@_>dZZG zPW6aiOT!J--9O?NG0%AP;}ge|4lDQN4=-}8`?JGwx}?mMnO)OdyQdu$nQCjPRV}jm z$u!Qa8E-cQ-r3Nz>Y(YPTd#BPEH+&8GWqfD!}4*53%dA!%#3$cIv;a~fq{X+)78&q Iol`;+0POUaApigX literal 0 HcmV?d00001 diff --git a/doc/html/images/warning.png b/doc/html/images/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..1c33db8f34a8b42b373179b46a2d8d8a10e061a9 GIT binary patch literal 1241 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8NW(e>JaphoO5CF?5GB9W| zFc>m0I59AIF)#!%FhnshWHT@nGcZ&$Ftji*^e`|?VPKe2T|Fl#Xiikroa*YO3=B&x zEth(EEp2I8I%UezrAyZ`FswB+TsvjTRtAQxnwndCdbZA)vvujxty{P5WnkF5cJ1D+ zTaPg?91{>YCLwX`*s*gA4Ce#{&Phm|)6~4iz;I1d^V+p*_ZS%N-Mjakf#JEL;`8Uv z-!m}0=iqq%{{43bhVS3M|7T$MKMF=efJz}yVEuRs0|NtNlDE4HLkFv@2Ll7c3r`ov zkcwNmlWOyu3izvS7ejxP>R-!INP5f(XN|IS^C^Iyp?`SUk1vQO?s(K&l| zi|Nkt0@~*ymDp65*E-HED6u(s{Mfrxmah{JrgAMTIq)Du?nC5nnYTRgThA|azEdIl zD^uvV>~q(b?>`Fd;xnAbe7so1I$-&keKN}|vNNOCvX<~g{)wp7{&hR__v^cBU*Gq* zV3YS!cBPWsl#eNWc|~nAXWMOB8tQWBuXo=4>}cytyX_5F^Az{bVJ>7~U~n#RjVKAu zPb(=;EJ|f?&`{R&%uP&B^-WCAOwLv?(KFJsP_VSrH?Yt*FjPn`$}BFabjYnNF3C*R zOD)z*DJ{s)E742N&z-nSaR&nfgBIAh%=Em(lG377hGY|?B=Z!b6jL*k#Ka_13kwTN zLrZf@a|7cv1EVApQ-8txlNlHo_&~Y>64O%|j7%zwOtcNO4T_>U4H+017(8A5T-G@y GGywozG)2h( literal 0 HcmV?d00001 diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 0000000..c7b0ad5 --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,110 @@ + + + +Chapter 1. Boost.Container + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
Next
+ + + + +

Last revised: August 26, 2011 at 17:45:38 GMT

+
+
Next
+ + diff --git a/doc/html/reference.css b/doc/html/reference.css new file mode 100644 index 0000000..1bf6b68 --- /dev/null +++ b/doc/html/reference.css @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2004 Joel de Guzman + + 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) +=============================================================================*/ +PRE.synopsis { + background-color: #e0ffff; + border: thin solid blue; + padding: 1em +} diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 new file mode 100644 index 0000000..1b4eb2d --- /dev/null +++ b/example/Jamfile.v2 @@ -0,0 +1,34 @@ +# Boost Container Library Example Jamfile + +# (C) Copyright Ion Gaztanaga 2009 +# Use, modification and distribution are 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) + +# Adapted from John Maddock's TR1 Jamfile.v2 +# Copyright John Maddock 2005. +# Use, modification and distribution are 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) + +# this rule enumerates through all the sources and invokes +# the run rule for each source, the result is a list of all +# the run rules, which we can pass on to the test_suite rule: + +rule test_all +{ + local all_rules = ; + + for local fileb in [ glob doc_*.cpp ] + { + all_rules += [ run $(fileb) + : # additional args + : # test-files + : # requirements + ] ; + } + + return $(all_rules) ; +} + +test-suite container_example : [ test_all r ] : multi ; \ No newline at end of file diff --git a/example/doc_emplace.cpp b/example/doc_emplace.cpp new file mode 100644 index 0000000..68e4a66 --- /dev/null +++ b/example/doc_emplace.cpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_emplace +#include +#include + +//Non-copyable and non-movable class +class non_copy_movable +{ + non_copy_movable(const non_copy_movable &); + non_copy_movable& operator=(const non_copy_movable &); + + public: + non_copy_movable(int = 0) {} +}; + +int main () +{ + using namespace boost::container; + + //Store non-copyable and non-movable objects in a list + list l; + non_copy_movable ncm; + + //A new element will be built calling non_copy_movable(int) contructor + l.emplace(l.begin(), 0); + assert(l.size() == 1); + + //A new element will be built calling the default constructor + l.emplace(l.begin()); + assert(l.size() == 2); + return 0; +} +//] +#include diff --git a/example/doc_move_containers.cpp b/example/doc_move_containers.cpp new file mode 100644 index 0000000..02e037c --- /dev/null +++ b/example/doc_move_containers.cpp @@ -0,0 +1,54 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_move_containers +#include +#include +#include + +//Non-copyable class +class non_copyable +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(non_copyable) + + public: + non_copyable(){} + non_copyable(BOOST_RV_REF(non_copyable)) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable)) { return *this; } +}; + +int main () +{ + using namespace boost::container; + + //Store non-copyable objects in a vector + vector v; + non_copyable nc; + v.push_back(boost::move(nc)); + assert(v.size() == 1); + + //Reserve no longer needs copy-constructible + v.reserve(100); + assert(v.capacity() >= 100); + + //This resize overload only needs movable and default constructible + v.resize(200); + assert(v.size() == 200); + + //Containers are also movable + vector v_other(boost::move(v)); + assert(v_other.size() == 200); + assert(v.empty()); + + return 0; +} +//] +#include diff --git a/example/doc_recursive_containers.cpp b/example/doc_recursive_containers.cpp new file mode 100644 index 0000000..b184d19 --- /dev/null +++ b/example/doc_recursive_containers.cpp @@ -0,0 +1,61 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_recursive_containers +#include +#include +#include +#include +#include + +using namespace boost::container; + +struct data +{ + int i_; + //A vector holding still undefined class 'data' + vector v_; + //A list holding still undefined 'data' + list l_; + //A map holding still undefined 'data' + map m_; + + friend bool operator <(const data &l, const data &r) + { return l.i_ < r.i_; } +}; + +struct tree_node +{ + string name; + string value; + + //children nodes of this node + list children_; +}; + + + +int main() +{ + //a container holding a recursive data type + stable_vector sv; + sv.resize(100); + + //Let's build a tree based in + //a recursive data type + tree_node root; + root.name = "root"; + root.value = "root_value"; + root.children_.resize(7); + return 0; +} +//] +#include diff --git a/example/doc_type_erasure.cpp b/example/doc_type_erasure.cpp new file mode 100644 index 0000000..04dca80 --- /dev/null +++ b/example/doc_type_erasure.cpp @@ -0,0 +1,91 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_type_erasure_MyClassHolder_h +#include + +//MyClassHolder.h + +//We don't need to include "MyClass.h" +//to store vector +class MyClass; + +class MyClassHolder +{ + public: + + void AddNewObject(const MyClass &o); + const MyClass & GetLastObject() const; + + private: + ::boost::container::vector vector_; +}; + +//] + +//[doc_type_erasure_MyClass_h + +//MyClass.h + +class MyClass +{ + private: + int value_; + + public: + MyClass(int val = 0) : value_(val){} + + friend bool operator==(const MyClass &l, const MyClass &r) + { return l.value_ == r.value_; } + //... +}; + +//] + + + +//[doc_type_erasure_main_cpp + +//Main.cpp + +//=#include "MyClassHolder.h" +//=#include "MyClass.h" + +#include + +int main() +{ + MyClass mc(7); + MyClassHolder myclassholder; + myclassholder.AddNewObject(mc); + return myclassholder.GetLastObject() == mc ? 0 : 1; +} +//] + +//[doc_type_erasure_MyClassHolder_cpp + +//MyClassHolder.cpp + +//=#include "MyClassHolder.h" + +//In the implementation MyClass must be a complete +//type so we include the appropriate header +//=#include "MyClass.h" + +void MyClassHolder::AddNewObject(const MyClass &o) +{ vector_.push_back(o); } + +const MyClass & MyClassHolder::GetLastObject() const +{ return vector_.back(); } + +//] + +#include diff --git a/index.html b/index.html new file mode 100644 index 0000000..ad39f65 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + + +Automatic redirection failed, please go to +../../doc/html/container.html + + diff --git a/proj/to-do.txt b/proj/to-do.txt new file mode 100644 index 0000000..c7f77cf --- /dev/null +++ b/proj/to-do.txt @@ -0,0 +1,2 @@ +->Change "insert" and "push_back"/"push_front" to catch non-const rvalues +->Add an example with stateful allocators diff --git a/proj/vc7ide/container.sln b/proj/vc7ide/container.sln new file mode 100644 index 0000000..ea29003 --- /dev/null +++ b/proj/vc7ide/container.sln @@ -0,0 +1,87 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deque_test", "deque_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792655}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flat_tree_test", "flat_tree_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792637}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list_test", "list_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792632}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stable_vector_test", "stable_vector_test.vcproj", "{5E11C8D3-FA52-760A-84FE-943A6BA05A21}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "string_test", "string_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D4A792607}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tree_test", "tree_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792606}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist_test", "slist_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792608}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vector_test", "vector_test.vcproj", "{5CE11C83-096A-84FE-4FA2-D3A6BA792002}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_containerlib", "container.vcproj", "{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.Build.0 = Release|Win32 + {5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Debug.ActiveCfg = Debug|Win32 + {5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Debug.Build.0 = Debug|Win32 + {5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Release.ActiveCfg = Release|Win32 + {5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D4A792607}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D4A792607}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D4A792607}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D4A792607}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792608}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792608}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792608}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792608}.Release.Build.0 = Release|Win32 + {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.ActiveCfg = Debug|Win32 + {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.Build.0 = Debug|Win32 + {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.ActiveCfg = Release|Win32 + {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.Build.0 = Release|Win32 + {FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Debug.ActiveCfg = Debug|Win32 + {FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Debug.Build.0 = Debug|Win32 + {FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Release.ActiveCfg = Release|Win32 + {FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/proj/vc7ide/container.vcproj b/proj/vc7ide/container.vcproj new file mode 100644 index 0000000..188564b --- /dev/null +++ b/proj/vc7ide/container.vcproj @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/deque_test.vcproj b/proj/vc7ide/deque_test.vcproj new file mode 100644 index 0000000..b416a71 --- /dev/null +++ b/proj/vc7ide/deque_test.vcproj @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/flat_tree_test.vcproj b/proj/vc7ide/flat_tree_test.vcproj new file mode 100644 index 0000000..4e05a16 --- /dev/null +++ b/proj/vc7ide/flat_tree_test.vcproj @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/list_ex.vcproj b/proj/vc7ide/list_ex.vcproj new file mode 100644 index 0000000..e3198de --- /dev/null +++ b/proj/vc7ide/list_ex.vcproj @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/slist_test.vcproj b/proj/vc7ide/slist_test.vcproj new file mode 100644 index 0000000..2e813bb --- /dev/null +++ b/proj/vc7ide/slist_test.vcproj @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/stable_vector_test.vcproj b/proj/vc7ide/stable_vector_test.vcproj new file mode 100644 index 0000000..fdc2192 --- /dev/null +++ b/proj/vc7ide/stable_vector_test.vcproj @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/string_test.vcproj b/proj/vc7ide/string_test.vcproj new file mode 100644 index 0000000..77f6f35 --- /dev/null +++ b/proj/vc7ide/string_test.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/tree_test.vcproj b/proj/vc7ide/tree_test.vcproj new file mode 100644 index 0000000..0231de2 --- /dev/null +++ b/proj/vc7ide/tree_test.vcproj @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/vector_test.vcproj b/proj/vc7ide/vector_test.vcproj new file mode 100644 index 0000000..270f5cf --- /dev/null +++ b/proj/vc7ide/vector_test.vcproj @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100644 index 0000000..6120122 --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,34 @@ +# Boost Container Library Test Jamfile + +# (C) Copyright Ion Gaztanaga 2009. +# Use, modification and distribution are 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) + +# Adapted from John Maddock's TR1 Jamfile.v2 +# Copyright John Maddock 2005. +# Use, modification and distribution are 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) + +# this rule enumerates through all the sources and invokes +# the run rule for each source, the result is a list of all +# the run rules, which we can pass on to the test_suite rule: + +rule test_all +{ + local all_rules = ; + + for local fileb in [ glob *.cpp ] + { + all_rules += [ run $(fileb) + : # additional args + : # test-files + : # requirements + ] ; + } + + return $(all_rules) ; +} + +test-suite container_test : [ test_all r ] ; diff --git a/test/check_equal_containers.hpp b/test/check_equal_containers.hpp new file mode 100644 index 0000000..ccdfa45 --- /dev/null +++ b/test/check_equal_containers.hpp @@ -0,0 +1,76 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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_TEST_CHECK_EQUAL_CONTAINERS_HPP +#define BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINERS_HPP + +#include +#include +#include +#include + +namespace boost{ +namespace container { +namespace test{ + +//Function to check if both containers are equal +template +bool CheckEqualContainers(MyBoostCont *boostcont, MyStdCont *stdcont) +{ + if(boostcont->size() != stdcont->size()) + return false; + + typedef typename MyBoostCont::value_type value_type; + + typename MyBoostCont::iterator itboost(boostcont->begin()), itboostend(boostcont->end()); + typename MyStdCont::iterator itstd(stdcont->begin()); + typename MyStdCont::size_type dist = (typename MyStdCont::size_type)std::distance(itboost, itboostend); + if(dist != boostcont->size()){ + return false; + } + std::size_t i = 0; + for(; itboost != itboostend; ++itboost, ++itstd, ++i){ + value_type val(*itstd); + const value_type &v = *itboost; + if(v != val) + return false; + } + return true; +} + +template +bool CheckEqualPairContainers(MyBoostCont *boostcont, MyStdCont *stdcont) +{ + if(boostcont->size() != stdcont->size()) + return false; + + typedef typename MyBoostCont::key_type key_type; + typedef typename MyBoostCont::mapped_type mapped_type; + + typename MyBoostCont::iterator itboost(boostcont->begin()), itboostend(boostcont->end()); + typename MyStdCont::iterator itstd(stdcont->begin()); + for(; itboost != itboostend; ++itboost, ++itstd){ + if(itboost->first != key_type(itstd->first)) + return false; + + if(itboost->second != mapped_type(itstd->second)) + return false; + } + return true; +} +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINERS_HPP diff --git a/test/deque_test.cpp b/test/deque_test.cpp new file mode 100644 index 0000000..ad4b7ac --- /dev/null +++ b/test/deque_test.cpp @@ -0,0 +1,295 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "print_container.hpp" +#include "check_equal_containers.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include +#include +#include +#include +#include "emplace_test.hpp" +#include "vector_test.hpp" + + +using namespace boost::container; + +//Explicit instantiation to detect compilation errors +template class boost::container::deque + < test::movable_and_copyable_int + , test::dummy_test_allocator >; + +//Function to check if both sets are equal +template +bool deque_copyable_only(V1 *, V2 *, containers_detail::false_type) +{ + return true; +} + +//Function to check if both sets are equal +template +bool deque_copyable_only(V1 *cntdeque, V2 *stddeque, containers_detail::true_type) +{ + typedef typename V1::value_type IntType; + std::size_t size = cntdeque->size(); + stddeque->insert(stddeque->end(), 50, 1); + cntdeque->insert(cntdeque->end(), 50, 1); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + { + IntType move_me(1); + stddeque->insert(stddeque->begin()+size/2, 50, 1); + cntdeque->insert(cntdeque->begin()+size/2, 50, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + { + IntType move_me(2); + cntdeque->assign(cntdeque->size()/2, boost::move(move_me)); + stddeque->assign(stddeque->size()/2, 2); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + { + IntType move_me(1); + stddeque->clear(); + cntdeque->clear(); + stddeque->insert(stddeque->begin(), 50, 1); + cntdeque->insert(cntdeque->begin(), 50, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + stddeque->insert(stddeque->begin()+20, 50, 1); + cntdeque->insert(cntdeque->begin()+20, 50, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + stddeque->insert(stddeque->begin()+20, 20, 1); + cntdeque->insert(cntdeque->begin()+20, 20, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + { + IntType move_me(1); + stddeque->clear(); + cntdeque->clear(); + stddeque->insert(stddeque->end(), 50, 1); + cntdeque->insert(cntdeque->end(), 50, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + stddeque->insert(stddeque->end()-20, 50, 1); + cntdeque->insert(cntdeque->end()-20, 50, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + stddeque->insert(stddeque->end()-20, 20, 1); + cntdeque->insert(cntdeque->end()-20, 20, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + + return true; +} + +//Test recursive structures +class recursive_deque +{ +public: + int id_; + deque deque_; +}; + +template +bool do_test() +{ + //Test for recursive types + { + deque recursive_deque_deque; + } + + { + //Now test move semantics + deque original; + deque move_ctor(boost::move(original)); + deque move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + + //Alias deque types + typedef deque MyCntDeque; + typedef std::deque MyStdDeque; + const int max = 100; + try{ + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyCntDeque *cntdeque = new MyCntDeque; + MyStdDeque *stddeque = new MyStdDeque; + //Compare several shared memory deque operations with std::deque + int i; + for(i = 0; i < max*100; ++i){ + IntType move_me(i); + cntdeque->insert(cntdeque->end(), boost::move(move_me)); + stddeque->insert(stddeque->end(), i); + } + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + cntdeque->clear(); + stddeque->clear(); + + for(i = 0; i < max*100; ++i){ + IntType move_me(i); + cntdeque->push_back(boost::move(move_me)); + stddeque->push_back(i); + } + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + cntdeque->clear(); + stddeque->clear(); + + for(i = 0; i < max*100; ++i){ + IntType move_me(i); + cntdeque->push_front(boost::move(move_me)); + stddeque->push_front(i); + } + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + typename MyCntDeque::iterator it; + typename MyCntDeque::const_iterator cit = it; + + cntdeque->erase(cntdeque->begin()++); + stddeque->erase(stddeque->begin()++); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + cntdeque->erase(cntdeque->begin()); + stddeque->erase(stddeque->begin()); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + { + //Initialize values + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me (-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + + cntdeque->insert(cntdeque->end() + ,boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(aux_vect + 50)); + stddeque->insert(stddeque->end(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + for(int i = 0, j = static_cast(cntdeque->size()); i < j; ++i){ + cntdeque->erase(cntdeque->begin()); + stddeque->erase(stddeque->begin()); + } + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + cntdeque->insert(cntdeque->begin() + ,boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(aux_vect + 50)); + stddeque->insert(stddeque->begin(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + + if(!deque_copyable_only(cntdeque, stddeque + ,containers_detail::bool_::value>())){ + return false; + } + + cntdeque->erase(cntdeque->begin()); + stddeque->erase(stddeque->begin()); + + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + for(i = 0; i < max; ++i){ + IntType move_me(i); + cntdeque->insert(cntdeque->begin(), boost::move(move_me)); + stddeque->insert(stddeque->begin(), i); + } + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + //Test insertion from list + { + std::list l(50, int(1)); + cntdeque->insert(cntdeque->begin(), l.begin(), l.end()); + stddeque->insert(stddeque->begin(), l.begin(), l.end()); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; + cntdeque->assign(l.begin(), l.end()); + stddeque->assign(l.begin(), l.end()); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; + } + + cntdeque->resize(100); + stddeque->resize(100); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; + + cntdeque->resize(200); + stddeque->resize(200); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; + + delete cntdeque; + delete stddeque; + } + catch(std::exception &ex){ + std::cout << ex.what() << std::endl; + return false; + } + + std::cout << std::endl << "Test OK!" << std::endl; + return true; +} + + +int main () +{ + if(!do_test()) + return 1; + + if(!do_test()) + return 1; + + { + typedef deque MyDeque; + typedef deque MyMoveDeque; + typedef deque MyCopyMoveDeque; + typedef deque MyCopyDeque; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + } + + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE); + + if(!boost::container::test::test_emplace + < deque, Options>()) + return 1; + + return 0; +} + +#include diff --git a/test/dummy_test_allocator.hpp b/test/dummy_test_allocator.hpp new file mode 100644 index 0000000..e03255e --- /dev/null +++ b/test/dummy_test_allocator.hpp @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_DUMMY_TEST_ALLOCATOR_HPP +#define BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes an allocator to test expand capabilities + +namespace boost { +namespace container { +namespace test { + +//This allocator just allows two allocations. The first one will return +//mp_buffer + m_offset configured in the constructor. The second one +//will return mp_buffer. +template +class dummy_test_allocator +{ + private: + typedef dummy_test_allocator self_t; + typedef void * aux_pointer_t; + typedef const void * cvoid_ptr; + + template + dummy_test_allocator& operator=(const dummy_test_allocator&); + + dummy_test_allocator& operator=(const dummy_test_allocator&); + + public: + typedef T value_type; + typedef T * pointer; + typedef const T * const_pointer; + typedef typename containers_detail::add_reference + ::type reference; + typedef typename containers_detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + +// typedef boost::container::version_type version; + + template + struct rebind + { typedef dummy_test_allocator other; }; + + //!Default constructor. Never throws + dummy_test_allocator() + {} + + //!Constructor from other dummy_test_allocator. Never throws + dummy_test_allocator(const dummy_test_allocator &) + {} + + //!Constructor from related dummy_test_allocator. Never throws + template + dummy_test_allocator(const dummy_test_allocator &) + {} + + pointer address(reference value) + { return pointer(addressof(value)); } + + const_pointer address(const_reference value) const + { return const_pointer(addressof(value)); } + + pointer allocate(size_type, cvoid_ptr = 0) + { return 0; } + + void deallocate(const pointer &, size_type) + { } + + template + void construct(pointer, const Convertible &) + {} + + void destroy(pointer) + {} + + size_type max_size() const + { return 0; } + + friend void swap(self_t &, self_t &) + {} + + //Experimental version 2 dummy_test_allocator functions + + std::pair + allocation_command(boost::container::allocation_type, + size_type, + size_type, + size_type &, const pointer & = 0) + { return std::pair(pointer(0), true); } + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. + size_type size(const pointer &) const + { return 0; } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::container::bad_alloc if there is no enough memory + pointer allocate_one() + { return pointer(0); } + + //!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(const pointer &) + {} +}; + +//!Equality test for same type of dummy_test_allocator +template inline +bool operator==(const dummy_test_allocator &, + const dummy_test_allocator &) +{ return false; } + +//!Inequality test for same type of dummy_test_allocator +template inline +bool operator!=(const dummy_test_allocator &, + const dummy_test_allocator &) +{ return true; } + +} //namespace test { +} //namespace container { +} //namespace boost { + +#include + +#endif //BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP + diff --git a/test/emplace_test.hpp b/test/emplace_test.hpp new file mode 100644 index 0000000..3cae3f8 --- /dev/null +++ b/test/emplace_test.hpp @@ -0,0 +1,625 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008. 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_TEST_EMPLACE_TEST_HPP +#define BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +namespace container { +namespace test{ + +class EmplaceInt +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(EmplaceInt) + + public: + EmplaceInt(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0) + : a_(a), b_(b), c_(c), d_(d), e_(e) + {} + + EmplaceInt(BOOST_RV_REF(EmplaceInt) o) + : a_(o.a_), b_(o.b_), c_(o.c_), d_(o.d_), e_(o.e_) + {} + + EmplaceInt& operator=(BOOST_RV_REF(EmplaceInt) o) + { + this->a_ = o.a_; + this->b_ = o.b_; + this->c_ = o.c_; + this->d_ = o.d_; + this->e_ = o.e_; + return *this; + } + + friend bool operator==(const EmplaceInt &l, const EmplaceInt &r) + { + return l.a_ == r.a_ && + l.b_ == r.b_ && + l.c_ == r.c_ && + l.d_ == r.d_ && + l.e_ == r.e_; + } + + friend bool operator<(const EmplaceInt &l, const EmplaceInt &r) + { return l.sum() < r.sum(); } + + friend bool operator>(const EmplaceInt &l, const EmplaceInt &r) + { return l.sum() > r.sum(); } + + friend bool operator!=(const EmplaceInt &l, const EmplaceInt &r) + { return !(l == r); } + + friend std::ostream &operator <<(std::ostream &os, const EmplaceInt &v) + { + os << "EmplaceInt: " << v.a_ << ' ' << v.b_ << ' ' << v.c_ << ' ' << v.d_ << ' ' << v.e_; + return os; + } + + ~EmplaceInt() + { a_ = b_ = c_ = d_ = e_ = 0; } + + //private: + int sum() const + { return this->a_ + this->b_ + this->c_ + this->d_ + this->e_; } + + int a_, b_, c_, d_, e_; + int padding[6]; +}; + + +} //namespace test { + +namespace test { + +enum EmplaceOptions{ + EMPLACE_BACK = 1 << 0, + EMPLACE_FRONT = 1 << 1, + EMPLACE_BEFORE = 1 << 2, + EMPLACE_AFTER = 1 << 3, + EMPLACE_ASSOC = 1 << 4, + EMPLACE_HINT = 1 << 5, + EMPLACE_ASSOC_PAIR = 1 << 6, + EMPLACE_HINT_PAIR = 1 << 7 +}; + +template +bool test_expected_container(const Container &ec, const EmplaceInt *Expected, unsigned int only_first_n) +{ + typedef typename Container::const_iterator const_iterator; + const_iterator itb(ec.begin()), ite(ec.end()); + unsigned int cur = 0; + if(only_first_n > ec.size()){ + return false; + } + for(; itb != ite && only_first_n--; ++itb, ++cur){ + const EmplaceInt & cr = *itb; + if(cr != Expected[cur]){ + return false; + } + } + return true; +} + +template +bool test_expected_container(const Container &ec, const std::pair *Expected, unsigned int only_first_n) +{ + typedef typename Container::const_iterator const_iterator; + const_iterator itb(ec.begin()), ite(ec.end()); + unsigned int cur = 0; + if(only_first_n > ec.size()){ + return false; + } + for(; itb != ite && only_first_n--; ++itb, ++cur){ + if(itb->first != Expected[cur].first){ + std::cout << "Error in first: " << itb->first << ' ' << Expected[cur].first << std::endl; + return false; + + } + else if(itb->second != Expected[cur].second){ + std::cout << "Error in second: " << itb->second << ' ' << Expected[cur].second << std::endl; + return false; + } + } + return true; +} + +static EmplaceInt expected [10]; + +typedef std::pair EmplaceIntPair; +static boost::aligned_storage::type pair_storage; + +static EmplaceIntPair* initialize_emplace_int_pair() +{ + EmplaceIntPair* ret = reinterpret_cast(&pair_storage); + for(unsigned int i = 0; i != 10; ++i){ + new(&ret->first)EmplaceInt(); + new(&ret->second)EmplaceInt(); + } + return ret; +} + +static EmplaceIntPair * expected_pair = initialize_emplace_int_pair(); + + +template +bool test_emplace_back(containers_detail::true_) +{ + std::cout << "Starting test_emplace_back." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + Container c; + c.emplace_back(); + if(!test_expected_container(c, &expected[0], 1)) + return false; + c.emplace_back(1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace_back(1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + c.emplace_back(1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + c.emplace_back(1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + c.emplace_back(1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + + return true; +} + +template +bool test_emplace_back(containers_detail::false_) +{ return true; } + +template +bool test_emplace_front(containers_detail::true_) +{ + std::cout << "Starting test_emplace_front." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + { + new(&expected [0]) EmplaceInt(1, 2, 3, 4, 5); + new(&expected [1]) EmplaceInt(1, 2, 3, 4); + new(&expected [2]) EmplaceInt(1, 2, 3); + new(&expected [3]) EmplaceInt(1, 2); + new(&expected [4]) EmplaceInt(1); + new(&expected [5]) EmplaceInt(); + Container c; + c.emplace_front(); + if(!test_expected_container(c, &expected[0] + 5, 1)) + return false; + c.emplace_front(1);/* + if(!test_expected_container(c, &expected[0] + 4, 2)) + return false; + c.emplace_front(1, 2); + if(!test_expected_container(c, &expected[0] + 3, 3)) + return false; + c.emplace_front(1, 2, 3); + if(!test_expected_container(c, &expected[0] + 2, 4)) + return false; + c.emplace_front(1, 2, 3, 4); + if(!test_expected_container(c, &expected[0] + 1, 5)) + return false; + c.emplace_front(1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0] + 0, 6)) + return false;*/ + } + return true; +} + +template +bool test_emplace_front(containers_detail::false_) +{ return true; } + +template +bool test_emplace_before(containers_detail::true_) +{ + std::cout << "Starting test_emplace_before." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(); + Container c; + c.emplace(c.cend(), 1); + c.emplace(c.cbegin()); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace(c.cend()); + if(!test_expected_container(c, &expected[0], 3)) + return false; + } + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + //emplace_front-like + Container c; + c.emplace(c.cbegin(), 1, 2, 3, 4, 5); + c.emplace(c.cbegin(), 1, 2, 3, 4); + c.emplace(c.cbegin(), 1, 2, 3); + c.emplace(c.cbegin(), 1, 2); + c.emplace(c.cbegin(), 1); + c.emplace(c.cbegin()); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace_back-like + typename Container::const_iterator i = c.emplace(c.cend()); + if(!test_expected_container(c, &expected[0], 1)) + return false; + i = c.emplace(++i, 1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + i = c.emplace(++i, 1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + i = c.emplace(++i, 1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + i = c.emplace(++i, 1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + i = c.emplace(++i, 1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace in the middle + c.emplace(c.cbegin()); + i = c.emplace(c.cend(), 1, 2, 3, 4, 5); + i = c.emplace(i, 1, 2, 3, 4); + i = c.emplace(i, 1, 2, 3); + i = c.emplace(i, 1, 2); + i = c.emplace(i, 1); + + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + return true; +} + +template +bool test_emplace_before(containers_detail::false_) +{ return true; } + +template +bool test_emplace_after(containers_detail::true_) +{ + std::cout << "Starting test_emplace_after." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(); + Container c; + typename Container::const_iterator i = c.emplace_after(c.cbefore_begin(), 1); + c.emplace_after(c.cbefore_begin()); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace_after(i); + if(!test_expected_container(c, &expected[0], 3)) + return false; + } + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + //emplace_front-like + Container c; + c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4, 5); + c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4); + c.emplace_after(c.cbefore_begin(), 1, 2, 3); + c.emplace_after(c.cbefore_begin(), 1, 2); + c.emplace_after(c.cbefore_begin(), 1); + c.emplace_after(c.cbefore_begin()); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace_back-like + typename Container::const_iterator i = c.emplace_after(c.cbefore_begin()); + if(!test_expected_container(c, &expected[0], 1)) + return false; + i = c.emplace_after(i, 1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + i = c.emplace_after(i, 1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + i = c.emplace_after(i, 1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + i = c.emplace_after(i, 1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + i = c.emplace_after(i, 1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace_after in the middle + i = c.emplace_after(c.cbefore_begin()); + c.emplace_after(i, 1, 2, 3, 4, 5); + c.emplace_after(i, 1, 2, 3, 4); + c.emplace_after(i, 1, 2, 3); + c.emplace_after(i, 1, 2); + c.emplace_after(i, 1); + + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + return true; +} + +template +bool test_emplace_after(containers_detail::false_) +{ return true; } + +template +bool test_emplace_assoc(containers_detail::true_) +{ + std::cout << "Starting test_emplace_assoc." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + { + Container c; + c.emplace(); + if(!test_expected_container(c, &expected[0], 1)) + return false; + c.emplace(1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace(1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + c.emplace(1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + c.emplace(1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + c.emplace(1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + return true; +} + +template +bool test_emplace_assoc(containers_detail::false_) +{ return true; } + +template +bool test_emplace_hint(containers_detail::true_) +{ + std::cout << "Starting test_emplace_hint." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + + { + Container c; + typename Container::const_iterator it; + it = c.emplace_hint(c.begin()); + if(!test_expected_container(c, &expected[0], 1)) + return false; + it = c.emplace_hint(it, 1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + it = c.emplace_hint(it, 1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + it = c.emplace_hint(it, 1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + it = c.emplace_hint(it, 1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + it = c.emplace_hint(it, 1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + + return true; +} + +template +bool test_emplace_hint(containers_detail::false_) +{ return true; } + +template +bool test_emplace_assoc_pair(containers_detail::true_) +{ + std::cout << "Starting test_emplace_assoc_pair." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected_pair[0].first) EmplaceInt(); + new(&expected_pair[0].second) EmplaceInt(); + new(&expected_pair[1].first) EmplaceInt(1); + new(&expected_pair[1].second) EmplaceInt(); + new(&expected_pair[2].first) EmplaceInt(2); + new(&expected_pair[2].second) EmplaceInt(2); + new(&expected_pair[3].first) EmplaceInt(3); + new(&expected_pair[3].second) EmplaceInt(2, 3); + new(&expected_pair[4].first) EmplaceInt(4); + new(&expected_pair[4].second) EmplaceInt(2, 3, 4); + new(&expected_pair[5].first) EmplaceInt(5); + new(&expected_pair[5].second) EmplaceInt(2, 3, 4, 5); + { + Container c; + c.emplace(); + if(!test_expected_container(c, &expected_pair[0], 1)){ + std::cout << "Error after c.emplace();\n"; + return false; + } + c.emplace(1); + if(!test_expected_container(c, &expected_pair[0], 2)){ + std::cout << "Error after c.emplace(1);\n"; + return false; + } + c.emplace(2, 2); + if(!test_expected_container(c, &expected_pair[0], 3)){ + std::cout << "Error after c.emplace(2, 2);\n"; + return false; + } + c.emplace(3, 2, 3); + if(!test_expected_container(c, &expected_pair[0], 4)){ + std::cout << "Error after c.emplace(3, 2, 3);\n"; + return false; + } + c.emplace(4, 2, 3, 4); + if(!test_expected_container(c, &expected_pair[0], 5)){ + std::cout << "Error after c.emplace(4, 2, 3, 4);\n"; + return false; + } + c.emplace(5, 2, 3, 4, 5); + if(!test_expected_container(c, &expected_pair[0], 6)){ + std::cout << "Error after c.emplace(5, 2, 3, 4, 5);\n"; + return false; + } + } + return true; +} + +template +bool test_emplace_assoc_pair(containers_detail::false_) +{ return true; } + +template +bool test_emplace_hint_pair(containers_detail::true_) +{ + std::cout << "Starting test_emplace_hint_pair." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected_pair[0].first) EmplaceInt(); + new(&expected_pair[0].second) EmplaceInt(); + new(&expected_pair[1].first) EmplaceInt(1); + new(&expected_pair[1].second) EmplaceInt(); + new(&expected_pair[2].first) EmplaceInt(2); + new(&expected_pair[2].second) EmplaceInt(2); + new(&expected_pair[3].first) EmplaceInt(3); + new(&expected_pair[3].second) EmplaceInt(2, 3); + new(&expected_pair[4].first) EmplaceInt(4); + new(&expected_pair[4].second) EmplaceInt(2, 3, 4); + new(&expected_pair[5].first) EmplaceInt(5); + new(&expected_pair[5].second) EmplaceInt(2, 3, 4, 5); + { + Container c; + typename Container::const_iterator it; + it = c.emplace_hint(c.begin()); + if(!test_expected_container(c, &expected_pair[0], 1)){ + std::cout << "Error after c.emplace(1);\n"; + return false; + } + it = c.emplace_hint(it, 1); + if(!test_expected_container(c, &expected_pair[0], 2)){ + std::cout << "Error after c.emplace(it, 1);\n"; + return false; + } + it = c.emplace_hint(it, 2, 2); + if(!test_expected_container(c, &expected_pair[0], 3)){ + std::cout << "Error after c.emplace(it, 2, 2);\n"; + return false; + } + it = c.emplace_hint(it, 3, 2, 3); + if(!test_expected_container(c, &expected_pair[0], 4)){ + std::cout << "Error after c.emplace(it, 3, 2, 3);\n"; + return false; + } + it = c.emplace_hint(it, 4, 2, 3, 4); + if(!test_expected_container(c, &expected_pair[0], 5)){ + std::cout << "Error after c.emplace(it, 4, 2, 3, 4);\n"; + return false; + } + it = c.emplace_hint(it, 5, 2, 3, 4, 5); + if(!test_expected_container(c, &expected_pair[0], 6)){ + std::cout << "Error after c.emplace(it, 5, 2, 3, 4, 5);\n"; + return false; + } + } + return true; +} + +template +bool test_emplace_hint_pair(containers_detail::false_) +{ return true; } + +template +struct emplace_active +{ + static const bool value = (0 != (O & Mask)); + typedef containers_detail::bool_ type; + operator type() const{ return type(); } +}; + +template +bool test_emplace() +{ +// if(!test_emplace_back(emplace_active())) +// return false; + if(!test_emplace_front(emplace_active())) + return false;/* + if(!test_emplace_before(emplace_active())) + return false; + if(!test_emplace_after(emplace_active())) + return false; + if(!test_emplace_assoc(emplace_active())) + return false; + if(!test_emplace_hint(emplace_active())) + return false; + if(!test_emplace_assoc_pair(emplace_active())) + return false; + if(!test_emplace_hint_pair(emplace_active())) + return false;*/ + return true; +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP diff --git a/test/expand_bwd_test_allocator.hpp b/test/expand_bwd_test_allocator.hpp new file mode 100644 index 0000000..1b690e3 --- /dev/null +++ b/test/expand_bwd_test_allocator.hpp @@ -0,0 +1,193 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_EXPAND_BWD_TEST_ALLOCATOR_HPP +#define BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes an allocator to test expand capabilities + +namespace boost { +namespace container { +namespace test { + +//This allocator just allows two allocations. The first one will return +//mp_buffer + m_offset configured in the constructor. The second one +//will return mp_buffer. +template +class expand_bwd_test_allocator +{ + private: + typedef expand_bwd_test_allocator self_t; + typedef void * aux_pointer_t; + typedef const void * cvoid_ptr; + + template + expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator&); + + expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator&); + + public: + typedef T value_type; + typedef T * pointer; + typedef const T * const_pointer; + typedef typename containers_detail::add_reference + ::type reference; + typedef typename containers_detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef boost::container::containers_detail::version_type version; + + template + struct rebind + { typedef expand_bwd_test_allocator other; }; + + //!Constructor from the segment manager. Never throws + expand_bwd_test_allocator(T *buffer, size_type size, difference_type offset) + : mp_buffer(buffer), m_size(size) + , m_offset(offset), m_allocations(0){ } + + //!Constructor from other expand_bwd_test_allocator. Never throws + expand_bwd_test_allocator(const expand_bwd_test_allocator &other) + : mp_buffer(other.mp_buffer), m_size(other.m_size) + , m_offset(other.m_offset), m_allocations(0){ } + + //!Constructor from related expand_bwd_test_allocator. Never throws + template + expand_bwd_test_allocator(const expand_bwd_test_allocator &other) + : mp_buffer(other.mp_buffer), m_size(other.m_size) + , m_offset(other.m_offset), m_allocations(0){ } + + pointer address(reference value) + { return pointer(addressof(value)); } + + const_pointer address(const_reference value) const + { return const_pointer(addressof(value)); } + + pointer allocate(size_type , cvoid_ptr hint = 0) + { (void)hint; return 0; } + + void deallocate(const pointer &, size_type) + {} + + template + void construct(pointer ptr, const Convertible &value) + { new((void*)ptr) value_type(value); } + + void destroy(pointer ptr) + { (*ptr).~value_type(); } + + size_type max_size() const + { return m_size; } + + friend void swap(self_t &alloc1, self_t &alloc2) + { + containers_detail::do_swap(alloc1.mp_buffer, alloc2.mp_buffer); + containers_detail::do_swap(alloc1.m_size, alloc2.m_size); + containers_detail::do_swap(alloc1.m_offset, alloc2.m_offset); + } + + //Experimental version 2 expand_bwd_test_allocator functions + + std::pair + allocation_command(boost::container::allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0) + { + (void)preferred_size; (void)reuse; (void)command; + //This allocator only expands backwards! + assert(m_allocations == 0 || (command & boost::container::expand_bwd)); + + received_size = limit_size; + + if(m_allocations == 0){ + if((m_offset + limit_size) > m_size){ + assert(0); + } + ++m_allocations; + return std::pair(mp_buffer + m_offset, false); + } + else if(m_allocations == 1){ + if(limit_size > m_size){ + assert(0); + } + ++m_allocations; + return std::pair(mp_buffer, true); + } + else{ + assert(0); + throw std::bad_alloc(); + } + } + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. + size_type size(const pointer &p) const + { (void)p; return m_size; } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::container::bad_alloc if there is no enough memory + pointer allocate_one() + { return this->allocate(1); } + + //!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(const pointer &p) + { return this->deallocate(p, 1); } + + pointer mp_buffer; + size_type m_size; + difference_type m_offset; + char m_allocations; +}; + +//!Equality test for same type of expand_bwd_test_allocator +template inline +bool operator==(const expand_bwd_test_allocator &alloc1, + const expand_bwd_test_allocator &alloc2) +{ return false; } + +//!Inequality test for same type of expand_bwd_test_allocator +template inline +bool operator!=(const expand_bwd_test_allocator &alloc1, + const expand_bwd_test_allocator &alloc2) +{ return true; } + +} //namespace test { +} //namespace container { +} //namespace boost { + +#include + +#endif //BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP + diff --git a/test/expand_bwd_test_template.hpp b/test/expand_bwd_test_template.hpp new file mode 100644 index 0000000..7dadcf9 --- /dev/null +++ b/test/expand_bwd_test_template.hpp @@ -0,0 +1,269 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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_TEST_ALLOCATION_TEST_TEMPLATE_HEADER +#define BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER + +#include +#include +#include +#include "expand_bwd_test_allocator.hpp" +#include +#include + +namespace boost { namespace container { namespace test { + +template +struct value_holder +{ + value_holder(T val) : m_value(val){} + value_holder(): m_value(0){} + ~value_holder(){ m_value = 0; } + bool operator == (const value_holder &other) const + { return m_value == other.m_value; } + bool operator != (const value_holder &other) const + { return m_value != other.m_value; } + + T m_value; +}; + +template +struct triple_value_holder +{ + triple_value_holder(T val) + : m_value1(val) + , m_value2(val) + , m_value3(val) + {} + + triple_value_holder() + : m_value1(0) + , m_value2(0) + , m_value3(0) + {} + + ~triple_value_holder() + { m_value1 = m_value2 = m_value3 = 0; } + + bool operator == (const triple_value_holder &other) const + { + return m_value1 == other.m_value1 + && m_value2 == other.m_value2 + && m_value3 == other.m_value3; + } + + bool operator != (const triple_value_holder &other) const + { + return m_value1 != other.m_value1 + || m_value2 != other.m_value2 + || m_value3 != other.m_value3; + } + + T m_value1; + T m_value2; + T m_value3; +}; + +typedef value_holder int_holder; +typedef triple_value_holder triple_int_holder; + + + +//Function to check if both sets are equal +template +bool CheckEqualVector(const Vector1 &vector1, const Vector2 &vector2) +{ + if(vector1.size() != vector2.size()) + return false; + return std::equal(vector1.begin(), vector1.end(), vector2.begin()); +} + +template +bool CheckUninitializedIsZero(const Vector & v) +{ + typedef typename Vector::value_type value_type; + typename Vector::size_type sz = v.size(); + typename Vector::size_type extra = v.capacity() - v.size(); + value_type comp(0); + + const value_type *holder = &v[0] + sz; + + while(extra--){ + if(*holder++ != comp) + return false; + } + return true; +} + + +//This function tests all the possible combinations when +//inserting data in a vector and expanding backwards +template +bool test_insert_with_expand_bwd() +{ + typedef typename VectorWithExpandBwdAllocator::value_type value_type; + typedef typename boost::remove_volatile::type non_volatile_value_type; + typedef std::vector Vect; + const int MemorySize = 1000; + + //Distance old and new buffer + const int Offset[] = + { 350, 250, 150, 150, + 150, 50, 50, 50 }; + //Insert position + const int Position[] = + { 100, 100, 100, 100, + 100, 100, 100, 100 }; + //Initial vector size + const int InitialSize[] = + { 200, 200, 200, 200, + 200, 200, 200, 200 }; + //Size of the data to insert + const int InsertSize[] = + { 100, 100, 100, 200, + 300, 25, 100, 200 }; + //Number of tests + const int Iterations = sizeof(InsertSize)/sizeof(int); + + for(int iteration = 0; iteration < Iterations; ++iteration) + { + value_type *memory = new value_type[MemorySize]; + try { + std::vector initial_data; + initial_data.resize(InitialSize[iteration]); + for(int i = 0; i < InitialSize[iteration]; ++i){ + initial_data[i] = i; + } + + Vect data_to_insert; + data_to_insert.resize(InsertSize[iteration]); + for(int i = 0; i < InsertSize[iteration]; ++i){ + data_to_insert[i] = -i; + } + + expand_bwd_test_allocator alloc + (&memory[0], MemorySize, Offset[iteration]); + VectorWithExpandBwdAllocator vector(alloc); + vector.insert( vector.begin() + , initial_data.begin(), initial_data.end()); + vector.insert( vector.begin() + Position[iteration] + , data_to_insert.begin(), data_to_insert.end()); + initial_data.insert(initial_data.begin() + Position[iteration] + , data_to_insert.begin(), data_to_insert.end()); + //Now check that values are equal + if(!CheckEqualVector(vector, initial_data)){ + std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl + << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl + << " Iteration: " << iteration << std::endl; + return false; + } + } + catch(...){ + delete [](const_cast(memory)); + throw; + } + delete [](const_cast(memory)); + } + + return true; +} + +//This function tests all the possible combinations when +//inserting data in a vector and expanding backwards +template +bool test_assign_with_expand_bwd() +{ + typedef typename VectorWithExpandBwdAllocator::value_type value_type; + typedef typename boost::remove_volatile::type non_volatile_value_type; + typedef std::vector Vect; + const int MemorySize = 200; + + const int Offset[] = { 50, 50, 50}; + const int InitialSize[] = { 25, 25, 25}; + const int AssignSize[] = { 40, 60, 80}; + const int Iterations = sizeof(AssignSize)/sizeof(int); + + for(int iteration = 0; iteration initial_data; + initial_data.resize(InitialSize[iteration]); + for(int i = 0; i < InitialSize[iteration]; ++i){ + initial_data[i] = i; + } + + //Create data to assign + std::vector data_to_assign; + data_to_assign.resize(AssignSize[iteration]); + for(int i = 0; i < AssignSize[iteration]; ++i){ + data_to_assign[i] = -i; + } + + //Insert initial data to the vector to test + expand_bwd_test_allocator alloc + (&memory[0], MemorySize, Offset[iteration]); + VectorWithExpandBwdAllocator vector(alloc); + vector.insert( vector.begin() + , initial_data.begin(), initial_data.end()); + + //Assign data + vector.assign(data_to_assign.begin(), data_to_assign.end()); + initial_data.assign(data_to_assign.begin(), data_to_assign.end()); + + //Now check that values are equal + if(!CheckEqualVector(vector, initial_data)){ + std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl + << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl + << " Iteration: " << iteration << std::endl; + return false; + } + } + catch(...){ + delete [](const_cast::type*>(memory)); + throw; + } + delete [](const_cast::type*>(memory)); + } + + return true; +} + +//This function calls all tests +template +bool test_all_expand_bwd() +{ + std::cout << "Starting test_insert_with_expand_bwd." << std::endl << " Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + + if(!test_insert_with_expand_bwd()){ + std::cout << "test_allocation_direct_deallocation failed. Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + return false; + } + + std::cout << "Starting test_assign_with_expand_bwd." << std::endl << " Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + + if(!test_assign_with_expand_bwd()){ + std::cout << "test_allocation_direct_deallocation failed. Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + return false; + } + + return true; +} + +}}} //namespace boost { namespace container { namespace test { + +#include + +#endif //BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp new file mode 100644 index 0000000..e8f9173 --- /dev/null +++ b/test/flat_tree_test.cpp @@ -0,0 +1,333 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "print_container.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "set_test.hpp" +#include "map_test.hpp" +#include "emplace_test.hpp" + +using namespace boost::container; + +//Alias allocator type +typedef std::allocator allocator_t; +typedef std::allocator + movable_allocator_t; +typedef std::allocator > + pair_allocator_t; +typedef std::allocator > + movable_pair_allocator_t; +typedef std::allocator + move_copy_allocator_t; +typedef std::allocator > + move_copy_pair_allocator_t; +typedef std::allocator + copy_allocator_t; +typedef std::allocator > + copy_pair_allocator_t; + + +//Alias set types +typedef std::set MyStdSet; +typedef std::multiset MyStdMultiSet; +typedef std::map MyStdMap; +typedef std::multimap MyStdMultiMap; + +typedef flat_set, allocator_t> MyBoostSet; +typedef flat_multiset, allocator_t> MyBoostMultiSet; +typedef flat_map, pair_allocator_t> MyBoostMap; +typedef flat_multimap, pair_allocator_t> MyBoostMultiMap; + +typedef flat_set + ,movable_allocator_t> MyMovableBoostSet; +typedef flat_multiset + ,movable_allocator_t> MyMovableBoostMultiSet; +typedef flat_map + ,movable_pair_allocator_t> MyMovableBoostMap; +typedef flat_multimap + ,movable_pair_allocator_t> MyMovableBoostMultiMap; + +typedef flat_set + ,move_copy_allocator_t> MyMoveCopyBoostSet; +typedef flat_multiset + ,move_copy_allocator_t> MyMoveCopyBoostMultiSet; +typedef flat_map + ,move_copy_pair_allocator_t> MyMoveCopyBoostMap; +typedef flat_multimap + ,move_copy_pair_allocator_t> MyMoveCopyBoostMultiMap; + +typedef flat_set + ,copy_allocator_t> MyCopyBoostSet; +typedef flat_multiset + ,copy_allocator_t> MyCopyBoostMultiSet; +typedef flat_map + ,copy_pair_allocator_t> MyCopyBoostMap; +typedef flat_multimap + ,copy_pair_allocator_t> MyCopyBoostMultiMap; + + + +//Test recursive structures +class recursive_flat_set +{ + public: + recursive_flat_set(const recursive_flat_set &c) + : id_(c.id_), flat_set_(c.flat_set_) + {} + + recursive_flat_set & operator =(const recursive_flat_set &c) + { + id_ = c.id_; + flat_set_= c.flat_set_; + return *this; + } + int id_; + flat_set flat_set_; + friend bool operator< (const recursive_flat_set &a, const recursive_flat_set &b) + { return a.id_ < b.id_; } +}; + + + +class recursive_flat_map +{ + public: + recursive_flat_map(const recursive_flat_map &c) + : id_(c.id_), map_(c.map_) + {} + + recursive_flat_map & operator =(const recursive_flat_map &c) + { + id_ = c.id_; + map_= c.map_; + return *this; + } + + int id_; + flat_map map_; + + friend bool operator< (const recursive_flat_map &a, const recursive_flat_map &b) + { return a.id_ < b.id_; } +}; + +//Test recursive structures +class recursive_flat_multiset +{ + public: + recursive_flat_multiset(const recursive_flat_multiset &c) + : id_(c.id_), flat_set_(c.flat_set_) + {} + + recursive_flat_multiset & operator =(const recursive_flat_multiset &c) + { + id_ = c.id_; + flat_set_= c.flat_set_; + return *this; + } + int id_; + flat_multiset flat_set_; + friend bool operator< (const recursive_flat_multiset &a, const recursive_flat_multiset &b) + { return a.id_ < b.id_; } +}; + +class recursive_flat_multimap +{ +public: + recursive_flat_multimap(const recursive_flat_multimap &c) + : id_(c.id_), map_(c.map_) + {} + + recursive_flat_multimap & operator =(const recursive_flat_multimap &c) + { + id_ = c.id_; + map_= c.map_; + return *this; + } + int id_; + flat_map map_; + friend bool operator< (const recursive_flat_multimap &a, const recursive_flat_multimap &b) + { return a.id_ < b.id_; } +}; + +template +void test_move() +{ + //Now test move semantics + C original; + C move_ctor(boost::move(original)); + C move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); +} + +int main() +{ + using namespace boost::container::test; + + //Now test move semantics + { + test_move >(); + test_move >(); + test_move >(); + test_move >(); + } + + + if (0 != set_test< + MyBoostSet + ,MyStdSet + ,MyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test_copyable< + MyBoostSet + ,MyStdSet + ,MyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test< + MyMovableBoostSet + ,MyStdSet + ,MyMovableBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test< + MyMoveCopyBoostSet + ,MyStdSet + ,MyMoveCopyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test_copyable< + MyMoveCopyBoostSet + ,MyStdSet + ,MyMoveCopyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test< + MyCopyBoostSet + ,MyStdSet + ,MyCopyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test_copyable< + MyCopyBoostSet + ,MyStdSet + ,MyCopyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test< + MyBoostMap + ,MyStdMap + ,MyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test_copyable< + MyBoostMap + ,MyStdMap + ,MyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + +// if (0 != map_test< +// MyMovableBoostMap +// ,MyStdMap +// ,MyMovableBoostMultiMap +// ,MyStdMultiMap>()){ +// return 1; +// } + + if (0 != map_test< + MyMoveCopyBoostMap + ,MyStdMap + ,MyMoveCopyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test_copyable< + MyMoveCopyBoostMap + ,MyStdMap + ,MyMoveCopyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test< + MyCopyBoostMap + ,MyStdMap + ,MyCopyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test_copyable< + MyCopyBoostMap + ,MyStdMap + ,MyCopyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC); + const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR); + +// if(!boost::container::test::test_emplace, MapOptions>()) +// return 1; + if(!boost::container::test::test_emplace, MapOptions>()) + return 1; + if(!boost::container::test::test_emplace, SetOptions>()) + return 1; + if(!boost::container::test::test_emplace, SetOptions>()) + return 1; + return 0; +} + +#include diff --git a/test/heap_allocator_v1.hpp b/test/heap_allocator_v1.hpp new file mode 100644 index 0000000..1e572c3 --- /dev/null +++ b/test/heap_allocator_v1.hpp @@ -0,0 +1,159 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. 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_HEAP_ALLOCATOR_V1_HPP +#define BOOST_CONTAINER_HEAP_ALLOCATOR_V1_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes an heap_allocator_v1 that allocates portions of fixed size +//!memory buffer (shared memory, mapped file...) + +namespace boost { +namespace container { +namespace test { + +//!An STL compatible heap_allocator_v1 that uses a segment manager as +//!memory source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the heap_allocator_v1 in shared memory, memory mapped-files, etc...*/ +template +class heap_allocator_v1 +{ + private: + typedef heap_allocator_v1 self_t; + typedef SegmentManager segment_manager; + typedef typename segment_manager::void_pointer aux_pointer_t; + + typedef typename + boost::pointer_to_other + ::type cvoid_ptr; + + typedef typename boost::pointer_to_other + ::type alloc_ptr_t; + + template + heap_allocator_v1& operator=(const heap_allocator_v1&); + + heap_allocator_v1& operator=(const heap_allocator_v1&); + + alloc_ptr_t mp_mngr; + + public: + typedef T value_type; + typedef typename boost::pointer_to_other + ::type pointer; + typedef typename boost:: + pointer_to_other::type const_pointer; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + //!Obtains an heap_allocator_v1 of other type + template + struct rebind + { + typedef heap_allocator_v1 other; + }; + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager()const + { return detail::get_pointer(mp_mngr); } +/* + //!Returns address of mutable object. Never throws + pointer address(reference value) const + { return pointer(addressof(value)); } + + //!Returns address of non mutable object. Never throws + const_pointer address(const_reference value) const + { return const_pointer(addressof(value)); } +*/ + //!Constructor from the segment manager. Never throws + heap_allocator_v1(segment_manager *segment_mngr) + : mp_mngr(segment_mngr) { } + + //!Constructor from other heap_allocator_v1. Never throws + heap_allocator_v1(const heap_allocator_v1 &other) + : mp_mngr(other.get_segment_manager()){ } + + //!Constructor from related heap_allocator_v1. Never throws + template + heap_allocator_v1(const heap_allocator_v1 &other) + : mp_mngr(other.get_segment_manager()){} + + //!Allocates memory for an array of count elements. + //!Throws boost::container::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_ptr hint = 0) + { (void)hint; return ::new value_type[count]; } + + //!Deallocates memory previously allocated. Never throws + void deallocate(const pointer &ptr, size_type) + { return ::delete[] detail::get_pointer(ptr) ; } + + //!Construct object, calling constructor. + //!Throws if T(const T&) throws + void construct(const pointer &ptr, const_reference value) + { new((void*)detail::get_pointer(ptr)) value_type(value); } + + //!Destroys object. Throws if object's destructor throws + void destroy(const pointer &ptr) + { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); } + + //!Returns the number of elements that could be allocated. Never throws + size_type max_size() const + { return mp_mngr->get_size(); } + + //!Swap segment manager. Does not throw. If each heap_allocator_v1 is placed in + //!different memory segments, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2) + { detail::do_swap(alloc1.mp_mngr, alloc2.mp_mngr); } +}; + +//!Equality test for same type of heap_allocator_v1 +template inline +bool operator==(const heap_allocator_v1 &alloc1, + const heap_allocator_v1 &alloc2) + { return alloc1.get_segment_manager() == alloc2.get_segment_manager(); } + +//!Inequality test for same type of heap_allocator_v1 +template inline +bool operator!=(const heap_allocator_v1 &alloc1, + const heap_allocator_v1 &alloc2) + { return alloc1.get_segment_manager() != alloc2.get_segment_manager(); } + +} //namespace test { +} //namespace container { +} //namespace boost { + +#include + +#endif //BOOST_CONTAINER_HEAP_ALLOCATOR_V1_HPP + diff --git a/test/list_test.cpp b/test/list_test.cpp new file mode 100644 index 0000000..9127ee1 --- /dev/null +++ b/test/list_test.cpp @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "list_test.hpp" +#include "emplace_test.hpp" + +using namespace boost::container; + +//Explicit instantiation to detect compilation errors +template class boost::container::list >; +typedef list MyList; + +typedef list MyMoveList; +typedef list MyCopyMoveList; +typedef list MyCopyList; + +class recursive_list +{ +public: + int id_; + list list_; + recursive_list &operator=(const recursive_list &o) + { list_ = o.list_; return *this; } +}; + +void recursive_list_test()//Test for recursive types +{ + list recursive, copy; + //Test to test both move emulations + if(!copy.size()){ + copy = recursive; + } +} + +int main () +{ + recursive_list_test(); + { + //Now test move semantics + list original; + list move_ctor(boost::move(original)); + list move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE); + + if(!boost::container::test::test_emplace, Options>()) + return 1; + + return 0; +} + +#include diff --git a/test/list_test.hpp b/test/list_test.hpp new file mode 100644 index 0000000..121c287 --- /dev/null +++ b/test/list_test.hpp @@ -0,0 +1,312 @@ +//////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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_TEST_LIST_TEST_HEADER +#define BOOST_CONTAINER_TEST_LIST_TEST_HEADER + +#include +#include "check_equal_containers.hpp" +#include +#include +#include +#include +#include "print_container.hpp" +#include +#include + +namespace boost{ +namespace container { +namespace test{ + +template +bool list_copyable_only(V1 *, V2 *, boost::container::containers_detail::false_type) +{ + return true; +} + +//Function to check if both sets are equal +template +bool list_copyable_only(V1 *boostlist, V2 *stdlist, boost::container::containers_detail::true_type) +{ + typedef typename V1::value_type IntType; + boostlist->insert(boostlist->end(), 50, IntType(1)); + stdlist->insert(stdlist->end(), 50, 1); + if(!test::CheckEqualContainers(boostlist, stdlist)) return false; + + { + IntType move_me(1); + boostlist->insert(boostlist->begin(), 50, boost::move(move_me)); + stdlist->insert(stdlist->begin(), 50, 1); + if(!test::CheckEqualContainers(boostlist, stdlist)) return false; + } + { + IntType move_me(2); + boostlist->assign(boostlist->size()/2, boost::move(move_me)); + stdlist->assign(stdlist->size()/2, 2); + if(!test::CheckEqualContainers(boostlist, stdlist)) return false; + } + { + IntType move_me(3); + boostlist->assign(boostlist->size()*3-1, boost::move(move_me)); + stdlist->assign(stdlist->size()*3-1, 3); + if(!test::CheckEqualContainers(boostlist, stdlist)) return false; + } + + { + IntType copy_me(3); + const IntType ccopy_me(3); + boostlist->push_front(copy_me); + stdlist->push_front(int(3)); + boostlist->push_front(ccopy_me); + stdlist->push_front(int(3)); + if(!test::CheckEqualContainers(boostlist, stdlist)) return false; + } + + return true; +} + +template +struct list_push_data_function +{ + template + static int execute(int max, MyBoostList *boostlist, MyStdList *stdlist) + { + typedef typename MyBoostList::value_type IntType; + for(int i = 0; i < max; ++i){ + IntType move_me(i); + boostlist->push_back(boost::move(move_me)); + stdlist->push_back(i); + boostlist->push_front(IntType(i)); + stdlist->push_front(int(i)); + } + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + return 0; + } +}; + +template<> +struct list_push_data_function +{ + template + static int execute(int max, MyBoostList *boostlist, MyStdList *stdlist) + { + typedef typename MyBoostList::value_type IntType; + for(int i = 0; i < max; ++i){ + IntType move_me(i); + boostlist->push_front(boost::move(move_me)); + stdlist->push_front(i); + boostlist->push_front(IntType(i)); + stdlist->push_front(int(i)); + } + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + return 0; + } +}; + +template +struct list_pop_back_function +{ + template + static int execute(MyBoostList *boostlist, MyStdList *stdlist) + { + boostlist->pop_back(); + stdlist->pop_back(); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + return 0; + } +}; + +template<> +struct list_pop_back_function +{ + template + static int execute(MyBoostList *boostlist, MyStdList *stdlist) + { + (void)boostlist; (void)stdlist; + return 0; + } +}; + +template +int list_test (bool copied_allocators_equal = true) +{ + typedef std::list MyStdList; + typedef typename MyBoostList::value_type IntType; + const int max = 100; + typedef list_push_data_function push_data_t; + + try{ + MyBoostList *boostlist = new MyBoostList; + MyStdList *stdlist = new MyStdList; + + if(push_data_t::execute(max, boostlist, stdlist)){ + return 1; + } + + boostlist->erase(boostlist->begin()++); + stdlist->erase(stdlist->begin()++); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + + if(list_pop_back_function::execute(boostlist, stdlist)){ + return 1; + } + + boostlist->pop_front(); + stdlist->pop_front(); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + boostlist->assign(boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(&aux_vect[50])); + stdlist->assign(&aux_vect2[0], &aux_vect2[50]); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + } + + if(copied_allocators_equal){ + boostlist->sort(); + stdlist->sort(); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + } + + boostlist->reverse(); + stdlist->reverse(); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + + boostlist->reverse(); + stdlist->reverse(); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + boostlist->insert(boostlist->begin() + ,boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(&aux_vect[50])); + stdlist->insert(stdlist->begin(), &aux_vect2[0], &aux_vect2[50]); + } + + boostlist->unique(); + stdlist->unique(); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + + if(copied_allocators_equal){ + boostlist->sort(std::greater()); + stdlist->sort(std::greater()); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + } + + for(int i = 0; i < max; ++i){ + IntType new_int(i); + boostlist->insert(boostlist->end(), boost::move(new_int)); + stdlist->insert(stdlist->end(), i); + if(!test::CheckEqualContainers(boostlist, stdlist)) return 1; + } + if(!test::CheckEqualContainers(boostlist, stdlist)) return 1; + + boostlist->resize(25); + stdlist->resize(25); + boostlist->resize(50); + stdlist->resize(50); + boostlist->resize(0); + stdlist->resize(0); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + + if(push_data_t::execute(max, boostlist, stdlist)){ + return 1; + } + { + MyBoostList otherboostlist(boostlist->get_allocator()); + MyStdList otherstdlist; + + int listsize = (int)boostlist->size(); + + if(push_data_t::execute(listsize, boostlist, stdlist)){ + return 1; + } + + if(copied_allocators_equal){ + boostlist->splice(boostlist->begin(), otherboostlist); + stdlist->splice(stdlist->begin(), otherstdlist); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + } + + listsize = (int)boostlist->size(); + + if(push_data_t::execute(listsize, boostlist, stdlist)){ + return 1; + } + + if(push_data_t::execute(listsize, &otherboostlist, &otherstdlist)){ + return 1; + } + + if(copied_allocators_equal){ + boostlist->sort(std::greater()); + stdlist->sort(std::greater()); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + + otherboostlist.sort(std::greater()); + otherstdlist.sort(std::greater()); + if(!CheckEqualContainers(&otherboostlist, &otherstdlist)) + return 1; + + boostlist->merge(otherboostlist, std::greater()); + stdlist->merge(otherstdlist, std::greater()); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + } + + if(!list_copyable_only(boostlist, stdlist + ,containers_detail::bool_::value>())){ + return 1; + } + } + + delete boostlist; + delete stdlist; + } + catch(...){ + throw; + } + return 0; +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif diff --git a/test/map_test.hpp b/test/map_test.hpp new file mode 100644 index 0000000..f41acba --- /dev/null +++ b/test/map_test.hpp @@ -0,0 +1,521 @@ +//////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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_TEST_MAP_TEST_HEADER +#define BOOST_CONTAINER_TEST_MAP_TEST_HEADER + +#include +#include "check_equal_containers.hpp" +#include +#include +#include +#include "print_container.hpp" +#include +#include +#include + +template +bool operator ==(std::pair &p1, std::pair &p2) +{ + return p1.first == p2.first && p1.second == p2.second; +} + +namespace boost{ +namespace container { +namespace test{ + +template +int map_test () +{ + typedef typename MyBoostMap::key_type IntType; + typedef containers_detail::pair IntPairType; + typedef typename MyStdMap::value_type StdPairType; + const int max = 100; + + try{ + MyBoostMap *boostmap = new MyBoostMap; + MyStdMap *stdmap = new MyStdMap; + MyBoostMultiMap *boostmultimap = new MyBoostMultiMap; + MyStdMultiMap *stdmultimap = new MyStdMultiMap; + + //Test construction from a range + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(i/2); + IntType i2(i/2); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + typedef typename MyStdMap::value_type StdValueType; + typedef typename MyStdMap::key_type StdKeyType; + typedef typename MyStdMap::mapped_type StdMappedType; + StdValueType aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2)); + } + + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(i/2); + IntType i2(i/2); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + MyBoostMap *boostmap2 = new MyBoostMap + ( boost::make_move_iterator(&aux_vect[0]) + , boost::make_move_iterator(aux_vect + 50)); + MyStdMap *stdmap2 = new MyStdMap(aux_vect2, aux_vect2 + 50); + MyBoostMultiMap *boostmultimap2 = new MyBoostMultiMap + ( boost::make_move_iterator(&aux_vect3[0]) + , boost::make_move_iterator(aux_vect3 + 50)); + MyStdMultiMap *stdmultimap2 = new MyStdMultiMap(aux_vect2, aux_vect2 + 50); + if(!CheckEqualContainers(boostmap2, stdmap2)) return 1; + if(!CheckEqualContainers(boostmultimap2, stdmultimap2)) return 1; + + //ordered range insertion + //This is really nasty, but we have no other simple choice + for(int i = 0; i < 50; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for(int i = 0; i < 50; ++i){ + new(&aux_vect2[i])StdValueType(StdKeyType(i), StdMappedType(i)); + } + + for(int i = 0; i < 50; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } +/* + MyBoostMap *boostmap3 = new MyBoostMap + ( ordered_unique_range + , boost::make_move_iterator(&aux_vect[0]) + , boost::make_move_iterator(aux_vect + 50)); + MyStdMap *stdmap3 = new MyStdMap(aux_vect2, aux_vect2 + 50); + MyBoostMultiMap *boostmultimap3 = new MyBoostMultiMap + ( ordered_range + , boost::make_move_iterator(&aux_vect3[0]) + , boost::make_move_iterator(aux_vect3 + 50)); + MyStdMultiMap *stdmultimap3 = new MyStdMultiMap(aux_vect2, aux_vect2 + 50); + + if(!CheckEqualContainers(boostmap3, stdmap3)){ + std::cout << "Error in construct(MyBoostMap3)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultimap3, stdmultimap3)){ + std::cout << "Error in construct(MyBoostMultiMap3)" << std::endl; + return 1; + } +*/ + delete boostmap2; + delete boostmultimap2; + delete stdmap2; + delete stdmultimap2; + //delete boostmap3; + //delete boostmultimap3; + //delete stdmap3; + //delete stdmultimap3; + } + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + IntPairType aux_vect3[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for(int i = 0; i < max; ++i){ + boostmap->insert(boost::move(aux_vect[i])); + stdmap->insert(StdPairType(i, i)); + boostmultimap->insert(boost::move(aux_vect3[i])); + stdmultimap->insert(StdPairType(i, i)); + } + + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + typename MyBoostMap::iterator it; + typename MyBoostMap::const_iterator cit = it; + + boostmap->erase(boostmap->begin()++); + stdmap->erase(stdmap->begin()++); + boostmultimap->erase(boostmultimap->begin()++); + stdmultimap->erase(stdmultimap->begin()++); + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + boostmap->erase(boostmap->begin()); + stdmap->erase(stdmap->begin()); + boostmultimap->erase(boostmultimap->begin()); + stdmultimap->erase(stdmultimap->begin()); + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + //Swapping test + MyBoostMap tmpboostemap2; + MyStdMap tmpstdmap2; + MyBoostMultiMap tmpboostemultimap2; + MyStdMultiMap tmpstdmultimap2; + boostmap->swap(tmpboostemap2); + stdmap->swap(tmpstdmap2); + boostmultimap->swap(tmpboostemultimap2); + stdmultimap->swap(tmpstdmultimap2); + boostmap->swap(tmpboostemap2); + stdmap->swap(tmpstdmap2); + boostmultimap->swap(tmpboostemultimap2); + stdmultimap->swap(tmpstdmultimap2); + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + } + //Insertion from other container + //Initialize values + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + boostmap->insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(aux_vect + 50)); + boostmultimap->insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50)); + for(std::size_t i = 0; i != 50; ++i){ + StdPairType stdpairtype(-1, -1); + stdmap->insert(stdpairtype); + stdmultimap->insert(stdpairtype); + } + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + for(int i = 0, j = static_cast(boostmap->size()); i < j; ++i){ + boostmap->erase(IntType(i)); + stdmap->erase(i); + boostmultimap->erase(IntType(i)); + stdmultimap->erase(i); + } + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + } + { + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + IntPairType aux_vect4[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect4[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + IntPairType aux_vect5[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect5[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + boostmap->insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(aux_vect + 50)); + boostmap->insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50)); + boostmultimap->insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(aux_vect4 + 50)); + boostmultimap->insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(aux_vect5 + 50)); + + for(std::size_t i = 0; i != 50; ++i){ + StdPairType stdpairtype(-1, -1); + stdmap->insert(stdpairtype); + stdmultimap->insert(stdpairtype); + stdmap->insert(stdpairtype); + stdmultimap->insert(stdpairtype); + } + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + boostmap->erase(boostmap->begin()->first); + stdmap->erase(stdmap->begin()->first); + boostmultimap->erase(boostmultimap->begin()->first); + stdmultimap->erase(stdmultimap->begin()->first); + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + } + + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + IntPairType aux_vect3[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for(int i = 0; i < max; ++i){ + boostmap->insert(boost::move(aux_vect[i])); + stdmap->insert(StdPairType(i, i)); + boostmultimap->insert(boost::move(aux_vect3[i])); + stdmultimap->insert(StdPairType(i, i)); + } + + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + for(int i = 0; i < max; ++i){ + IntPairType intpair; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmap->insert(boostmap->begin(), boost::move(intpair)); + stdmap->insert(stdmap->begin(), StdPairType(i, i)); + //PrintContainers(boostmap, stdmap); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmultimap->insert(boostmultimap->begin(), boost::move(intpair)); + stdmultimap->insert(stdmultimap->begin(), StdPairType(i, i)); + //PrintContainers(boostmultimap, stdmultimap); + if(!CheckEqualPairContainers(boostmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) + return 1; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmap->insert(boostmap->end(), boost::move(intpair)); + stdmap->insert(stdmap->end(), StdPairType(i, i)); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmultimap->insert(boostmultimap->end(), boost::move(intpair)); + stdmultimap->insert(stdmultimap->end(), StdPairType(i, i)); + if(!CheckEqualPairContainers(boostmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) + return 1; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmap->insert(boostmap->lower_bound(IntType(i)), boost::move(intpair)); + stdmap->insert(stdmap->lower_bound(i), StdPairType(i, i)); + //PrintContainers(boostmap, stdmap); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + { + IntType i1(i); + boostmultimap->insert(boostmultimap->lower_bound(boost::move(i1)), boost::move(intpair)); + stdmultimap->insert(stdmultimap->lower_bound(i), StdPairType(i, i)); + } + + //PrintContainers(boostmultimap, stdmultimap); + if(!CheckEqualPairContainers(boostmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) + return 1; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + { + IntType i1(i); + boostmap->insert(boostmap->upper_bound(boost::move(i1)), boost::move(intpair)); + stdmap->insert(stdmap->upper_bound(i), StdPairType(i, i)); + } + //PrintContainers(boostmap, stdmap); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + { + IntType i1(i); + boostmultimap->insert(boostmultimap->upper_bound(boost::move(i1)), boost::move(intpair)); + stdmultimap->insert(stdmultimap->upper_bound(i), StdPairType(i, i)); + } + //PrintContainers(boostmultimap, stdmultimap); + if(!CheckEqualPairContainers(boostmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) + return 1; + } + + //Compare count with std containers + for(int i = 0; i < max; ++i){ + if(boostmap->count(IntType(i)) != stdmap->count(i)){ + return -1; + } + + if(boostmultimap->count(IntType(i)) != stdmultimap->count(i)){ + return -1; + } + } + + //Now do count exercise + boostmap->erase(boostmap->begin(), boostmap->end()); + boostmultimap->erase(boostmultimap->begin(), boostmultimap->end()); + boostmap->clear(); + boostmultimap->clear(); + + for(int j = 0; j < 3; ++j) + for(int i = 0; i < 100; ++i){ + IntPairType intpair; + { + IntType i1(i), i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmap->insert(boost::move(intpair)); + { + IntType i1(i), i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmultimap->insert(boost::move(intpair)); + if(boostmap->count(IntType(i)) != typename MyBoostMultiMap::size_type(1)) + return 1; + if(boostmultimap->count(IntType(i)) != typename MyBoostMultiMap::size_type(j+1)) + return 1; + } + } + + delete boostmap; + delete stdmap; + delete boostmultimap; + delete stdmultimap; + } + catch(...){ + throw; + } + return 0; +} + +template +int map_test_copyable () +{ + typedef typename MyBoostMap::key_type IntType; + typedef containers_detail::pair IntPairType; + typedef typename MyStdMap::value_type StdPairType; + + const int max = 100; + + try{ + MyBoostMap *boostmap = new MyBoostMap; + MyStdMap *stdmap = new MyStdMap; + MyBoostMultiMap *boostmultimap = new MyBoostMultiMap; + MyStdMultiMap *stdmultimap = new MyStdMultiMap; + + int i; + for(i = 0; i < max; ++i){ + { + IntType i1(i), i2(i); + IntPairType intpair1(boost::move(i1), boost::move(i2)); + boostmap->insert(boost::move(intpair1)); + stdmap->insert(StdPairType(i, i)); + } + { + IntType i1(i), i2(i); + IntPairType intpair2(boost::move(i1), boost::move(i2)); + boostmultimap->insert(boost::move(intpair2)); + stdmultimap->insert(StdPairType(i, i)); + } + } + if(!CheckEqualContainers(boostmap, stdmap)) return 1; + if(!CheckEqualContainers(boostmultimap, stdmultimap)) return 1; + + { + //Now, test copy constructor + MyBoostMap boostmapcopy(*boostmap); + MyStdMap stdmapcopy(*stdmap); + MyBoostMultiMap boostmmapcopy(*boostmultimap); + MyStdMultiMap stdmmapcopy(*stdmultimap); + + if(!CheckEqualContainers(&boostmapcopy, &stdmapcopy)) + return 1; + if(!CheckEqualContainers(&boostmmapcopy, &stdmmapcopy)) + return 1; + + //And now assignment + boostmapcopy = *boostmap; + stdmapcopy = *stdmap; + boostmmapcopy = *boostmultimap; + stdmmapcopy = *stdmultimap; + + if(!CheckEqualContainers(&boostmapcopy, &stdmapcopy)) + return 1; + if(!CheckEqualContainers(&boostmmapcopy, &stdmmapcopy)) + return 1; + delete boostmap; + delete boostmultimap; + delete stdmap; + delete stdmultimap; + } + } + catch(...){ + throw; + } + return 0; +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_CONTAINER_TEST_MAP_TEST_HEADER diff --git a/test/movable_int.hpp b/test/movable_int.hpp new file mode 100644 index 0000000..37bf71d --- /dev/null +++ b/test/movable_int.hpp @@ -0,0 +1,230 @@ +/////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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_TEST_MOVABLE_INT_HEADER +#define BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER + +#include +#include +#include + +namespace boost { +namespace container { +namespace test { + +template +struct is_copyable; + +template<> +struct is_copyable +{ + static const bool value = true; +}; + + +class movable_int +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_int) + + public: + movable_int() + : m_int(0) + {} + + explicit movable_int(int a) + : m_int(a) + {} + + movable_int(BOOST_RV_REF(movable_int) mmi) + : m_int(mmi.m_int) + { mmi.m_int = 0; } + + movable_int & operator= (BOOST_RV_REF(movable_int) mmi) + { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; } + + movable_int & operator= (int i) + { this->m_int = i; return *this; } + + bool operator ==(const movable_int &mi) const + { return this->m_int == mi.m_int; } + + bool operator !=(const movable_int &mi) const + { return this->m_int != mi.m_int; } + + bool operator <(const movable_int &mi) const + { return this->m_int < mi.m_int; } + + bool operator <=(const movable_int &mi) const + { return this->m_int <= mi.m_int; } + + bool operator >=(const movable_int &mi) const + { return this->m_int >= mi.m_int; } + + bool operator >(const movable_int &mi) const + { return this->m_int > mi.m_int; } + + int get_int() const + { return m_int; } + + private: + int m_int; +}; + +template +std::basic_ostream & operator<< + (std::basic_ostream & os, movable_int const & p) + +{ + os << p.get_int(); + return os; +} + + +template<> +struct is_copyable +{ + static const bool value = false; +}; + +class movable_and_copyable_int +{ + BOOST_COPYABLE_AND_MOVABLE(movable_and_copyable_int) + + public: + movable_and_copyable_int() + : m_int(0) + {} + + explicit movable_and_copyable_int(int a) + : m_int(a) + {} + + movable_and_copyable_int(const movable_and_copyable_int& mmi) + : m_int(mmi.m_int) + {} + + movable_and_copyable_int(BOOST_RV_REF(movable_and_copyable_int) mmi) + : m_int(mmi.m_int) + { mmi.m_int = 0; } + + movable_and_copyable_int &operator= (BOOST_COPY_ASSIGN_REF(movable_and_copyable_int) mi) + { this->m_int = mi.m_int; return *this; } + + movable_and_copyable_int & operator= (BOOST_RV_REF(movable_and_copyable_int) mmi) + { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; } + + movable_and_copyable_int & operator= (int i) + { this->m_int = i; return *this; } + + bool operator ==(const movable_and_copyable_int &mi) const + { return this->m_int == mi.m_int; } + + bool operator !=(const movable_and_copyable_int &mi) const + { return this->m_int != mi.m_int; } + + bool operator <(const movable_and_copyable_int &mi) const + { return this->m_int < mi.m_int; } + + bool operator <=(const movable_and_copyable_int &mi) const + { return this->m_int <= mi.m_int; } + + bool operator >=(const movable_and_copyable_int &mi) const + { return this->m_int >= mi.m_int; } + + bool operator >(const movable_and_copyable_int &mi) const + { return this->m_int > mi.m_int; } + + int get_int() const + { return m_int; } + + private: + int m_int; +}; + +template +std::basic_ostream & operator<< + (std::basic_ostream & os, movable_and_copyable_int const & p) + +{ + os << p.get_int(); + return os; +} + +template<> +struct is_copyable +{ + static const bool value = true; +}; + +class copyable_int +{ + public: + copyable_int() + : m_int(0) + {} + + explicit copyable_int(int a) + : m_int(a) + {} + + copyable_int(const copyable_int& mmi) + : m_int(mmi.m_int) + {} + + copyable_int & operator= (int i) + { this->m_int = i; return *this; } + + bool operator ==(const copyable_int &mi) const + { return this->m_int == mi.m_int; } + + bool operator !=(const copyable_int &mi) const + { return this->m_int != mi.m_int; } + + bool operator <(const copyable_int &mi) const + { return this->m_int < mi.m_int; } + + bool operator <=(const copyable_int &mi) const + { return this->m_int <= mi.m_int; } + + bool operator >=(const copyable_int &mi) const + { return this->m_int >= mi.m_int; } + + bool operator >(const copyable_int &mi) const + { return this->m_int > mi.m_int; } + + int get_int() const + { return m_int; } + + private: + int m_int; +}; + +template +std::basic_ostream & operator<< + (std::basic_ostream & os, copyable_int const & p) + +{ + os << p.get_int(); + return os; +} + +template<> +struct is_copyable +{ + static const bool value = true; +}; + +} //namespace test { +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER diff --git a/test/print_container.hpp b/test/print_container.hpp new file mode 100644 index 0000000..9300c3c --- /dev/null +++ b/test/print_container.hpp @@ -0,0 +1,64 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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_PRINTCONTAINER_HPP +#define BOOST_PRINTCONTAINER_HPP + +#include +#include +#include +#include + +namespace boost{ +namespace container { +namespace test{ + +struct PrintValues : public std::unary_function +{ + void operator() (int value) const + { + std::cout << value << " "; + } +}; + +template +void PrintContents(const Container &cont, const char *contName) +{ + std::cout<< "Printing contents of " << contName << std::endl; + std::for_each(cont.begin(), cont.end(), PrintValues()); + std::cout<< std::endl << std::endl; +} + +//Function to dump data +template +void PrintContainers(MyBoostCont *boostcont, MyStdCont *stdcont) +{ + typename MyBoostCont::iterator itboost = boostcont->begin(), itboostend = boostcont->end(); + typename MyStdCont::iterator itstd = stdcont->begin(), itstdend = stdcont->end(); + + std::cout << "MyBoostCont" << std::endl; + for(; itboost != itboostend; ++itboost){ + std::cout << *itboost << std::endl; + } + std::cout << "MyStdCont" << std::endl; + + for(; itstd != itstdend; ++itstd){ + std::cout << *itstd << std::endl; + } +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_PRINTCONTAINER_HPP diff --git a/test/set_test.hpp b/test/set_test.hpp new file mode 100644 index 0000000..e4061eb --- /dev/null +++ b/test/set_test.hpp @@ -0,0 +1,504 @@ +//////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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_TEST_SET_TEST_HEADER +#define BOOST_CONTAINER_TEST_SET_TEST_HEADER + +#include +#include "check_equal_containers.hpp" +#include +#include +#include +#include "print_container.hpp" +#include +#include + +namespace boost{ +namespace container { +namespace test{ + +template +int set_test () +{ + typedef typename MyBoostSet::value_type IntType; + const int max = 100; + + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyBoostSet *boostset = new MyBoostSet; + MyStdSet *stdset = new MyStdSet; + MyBoostMultiSet *boostmultiset = new MyBoostMultiSet; + MyStdMultiSet *stdmultiset = new MyStdMultiSet; + + //Test construction from a range + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(i/2); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = i/2; + } + IntType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(i/2); + aux_vect3[i] = boost::move(move_me); + } + + MyBoostSet *boostset2 = new MyBoostSet + ( boost::make_move_iterator(&aux_vect[0]) + , boost::make_move_iterator(aux_vect + 50)); + MyStdSet *stdset2 = new MyStdSet(aux_vect2, aux_vect2 + 50); + MyBoostMultiSet *boostmultiset2 = new MyBoostMultiSet + ( boost::make_move_iterator(&aux_vect3[0]) + , boost::make_move_iterator(aux_vect3 + 50)); + MyStdMultiSet *stdmultiset2 = new MyStdMultiSet(aux_vect2, aux_vect2 + 50); + if(!CheckEqualContainers(boostset2, stdset2)){ + std::cout << "Error in construct(MyBoostSet2)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset2, stdmultiset2)){ + std::cout << "Error in construct(MyBoostMultiSet2)" << std::endl; + return 1; + } + + //ordered range insertion + for(int i = 0; i < 50; ++i){ + IntType move_me(i); + aux_vect[i] = boost::move(move_me); + } + + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = i; + } + + for(int i = 0; i < 50; ++i){ + IntType move_me(i); + aux_vect3[i] = boost::move(move_me); + } +/* + MyBoostSet *boostset3 = MyBoostSet + ( ordered_unique_range + , boost::make_move_iterator(&aux_vect[0]) + , boost::make_move_iterator(aux_vect + 50)); + MyStdSet *stdset3 = new MyStdSet(aux_vect2, aux_vect2 + 50); + MyBoostMultiSet *boostmultiset3 = MyBoostMultiSet + ( ordered_range + , boost::make_move_iterator(&aux_vect3[0]) + , boost::make_move_iterator(aux_vect3 + 50)); + MyStdMultiSet *stdmultiset3 = new MyStdMultiSet(aux_vect2, aux_vect2 + 50); + + if(!CheckEqualContainers(boostset3, stdset3)){ + std::cout << "Error in construct(MyBoostSet3)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset3, stdmultiset3)){ + std::cout << "Error in construct(MyBoostMultiSet3)" << std::endl; + return 1; + } +*/ + delete boostset2; + delete boostmultiset2; + delete stdset2; + delete stdmultiset2; + //delete boostset3; + //delete boostmultiset3; + //delete stdset3; + //delete stdmultiset3; + } + + int i, j; + for(i = 0; i < max; ++i){ + IntType move_me(i); + boostset->insert(boost::move(move_me)); + stdset->insert(i); + boostset->insert(IntType(i)); + stdset->insert(i); + IntType move_me2(i); + boostmultiset->insert(boost::move(move_me2)); + stdmultiset->insert(i); + boostmultiset->insert(IntType(i)); + stdmultiset->insert(i); + } + + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boost::move(move_me)" << std::endl; + return 1; + } + + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boost::move(move_me)" << std::endl; + return 1; + } + + typename MyBoostSet::iterator it; + typename MyBoostSet::const_iterator cit = it; + + boostset->erase(boostset->begin()++); + stdset->erase(stdset->begin()++); + boostmultiset->erase(boostmultiset->begin()++); + stdmultiset->erase(stdmultiset->begin()++); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->erase(boostset->begin()++)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->erase(boostmultiset->begin()++)" << std::endl; + return 1; + } + + boostset->erase(boostset->begin()); + stdset->erase(stdset->begin()); + boostmultiset->erase(boostmultiset->begin()); + stdmultiset->erase(stdmultiset->begin()); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->erase(boostset->begin())" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->erase(boostmultiset->begin())" << std::endl; + return 1; + } + + //Swapping test + MyBoostSet tmpboosteset2; + MyStdSet tmpstdset2; + MyBoostMultiSet tmpboostemultiset2; + MyStdMultiSet tmpstdmultiset2; + boostset->swap(tmpboosteset2); + stdset->swap(tmpstdset2); + boostmultiset->swap(tmpboostemultiset2); + stdmultiset->swap(tmpstdmultiset2); + boostset->swap(tmpboosteset2); + stdset->swap(tmpstdset2); + boostmultiset->swap(tmpboostemultiset2); + stdmultiset->swap(tmpstdmultiset2); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->swap(tmpboosteset2)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->swap(tmpboostemultiset2)" << std::endl; + return 1; + } + + //Insertion from other container + //Initialize values + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + IntType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect3[i] = boost::move(move_me); + } + + boostset->insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(aux_vect + 50)); + stdset->insert(aux_vect2, aux_vect2 + 50); + boostmultiset->insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50)); + stdmultiset->insert(aux_vect2, aux_vect2 + 50); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boost::make_move_iterator(&aux_vect[0])..." << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boost::make_move_iterator(&aux_vect3[0]), ..." << std::endl; + return 1; + } + + for(int i = 0, j = static_cast(boostset->size()); i < j; ++i){ + IntType erase_me(i); + boostset->erase(erase_me); + stdset->erase(i); + boostmultiset->erase(erase_me); + stdmultiset->erase(i); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->erase(erase_me)" << boostset->size() << " " << stdset->size() << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->erase(erase_me)" << std::endl; + return 1; + } + } + } + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + IntType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect3[i] = boost::move(move_me); + } + + IntType aux_vect4[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect4[i] = boost::move(move_me); + } + + IntType aux_vect5[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect5[i] = boost::move(move_me); + } + + boostset->insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(aux_vect + 50)); + boostset->insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50)); + stdset->insert(aux_vect2, aux_vect2 + 50); + stdset->insert(aux_vect2, aux_vect2 + 50); + boostmultiset->insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(aux_vect4 + 50)); + boostmultiset->insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(aux_vect5 + 50)); + stdmultiset->insert(aux_vect2, aux_vect2 + 50); + stdmultiset->insert(aux_vect2, aux_vect2 + 50); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boost::make_move_iterator(&aux_vect3[0])..." << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boost::make_move_iterator(&aux_vect5[0])..." << std::endl; + return 1; + } + + boostset->erase(*boostset->begin()); + stdset->erase(*stdset->begin()); + boostmultiset->erase(*boostmultiset->begin()); + stdmultiset->erase(*stdmultiset->begin()); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->erase(*boostset->begin())" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->erase(*boostmultiset->begin())" << std::endl; + return 1; + } + } + + for(i = 0; i < max; ++i){ + IntType move_me(i); + boostset->insert(boost::move(move_me)); + stdset->insert(i); + IntType move_me2(i); + boostmultiset->insert(boost::move(move_me2)); + stdmultiset->insert(i); + } + + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boost::move(move_me)) try 2" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boost::move(move_me2)) try 2" << std::endl; + return 1; + } + + for(i = 0; i < max; ++i){ + IntType move_me(i); + boostset->insert(boostset->begin(), boost::move(move_me)); + stdset->insert(stdset->begin(), i); + //PrintContainers(boostset, stdset); + IntType move_me2(i); + boostmultiset->insert(boostmultiset->begin(), boost::move(move_me2)); + stdmultiset->insert(stdmultiset->begin(), i); + //PrintContainers(boostmultiset, stdmultiset); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boostset->begin(), boost::move(move_me))" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boostmultiset->begin(), boost::move(move_me2))" << std::endl; + return 1; + } + + IntType move_me3(i); + boostset->insert(boostset->end(), boost::move(move_me3)); + stdset->insert(stdset->end(), i); + IntType move_me4(i); + boostmultiset->insert(boostmultiset->end(), boost::move(move_me4)); + stdmultiset->insert(stdmultiset->end(), i); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boostset->end(), boost::move(move_me3))" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boostmultiset->end(), boost::move(move_me4))" << std::endl; + return 1; + } + { + IntType move_me(i); + boostset->insert(boostset->upper_bound(move_me), boost::move(move_me)); + stdset->insert(stdset->upper_bound(i), i); + //PrintContainers(boostset, stdset); + IntType move_me2(i); + boostmultiset->insert(boostmultiset->upper_bound(move_me2), boost::move(move_me2)); + stdmultiset->insert(stdmultiset->upper_bound(i), i); + //PrintContainers(boostmultiset, stdmultiset); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boostset->upper_bound(move_me), boost::move(move_me))" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boostmultiset->upper_bound(move_me2), boost::move(move_me2))" << std::endl; + return 1; + } + + } + { + IntType move_me(i); + boostset->insert(boostset->lower_bound(move_me), boost::move(move_me2)); + stdset->insert(stdset->lower_bound(i), i); + //PrintContainers(boostset, stdset); + IntType move_me2(i); + boostmultiset->insert(boostmultiset->lower_bound(move_me2), boost::move(move_me2)); + stdmultiset->insert(stdmultiset->lower_bound(i), i); + //PrintContainers(boostmultiset, stdmultiset); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boostset->lower_bound(move_me), boost::move(move_me2))" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boostmultiset->lower_bound(move_me2), boost::move(move_me2))" << std::endl; + return 1; + } + } + } + + //Compare count with std containers + for(i = 0; i < max; ++i){ + IntType count_me(i); + if(boostset->count(count_me) != stdset->count(i)){ + return -1; + } + if(boostmultiset->count(count_me) != stdmultiset->count(i)){ + return -1; + } + } + + //Now do count exercise + boostset->erase(boostset->begin(), boostset->end()); + boostmultiset->erase(boostmultiset->begin(), boostmultiset->end()); + boostset->clear(); + boostmultiset->clear(); + + for(j = 0; j < 3; ++j) + for(i = 0; i < 100; ++i){ + IntType move_me(i); + boostset->insert(boost::move(move_me)); + IntType move_me2(i); + boostmultiset->insert(boost::move(move_me2)); + IntType count_me(i); + if(boostset->count(count_me) != typename MyBoostMultiSet::size_type(1)){ + std::cout << "Error in boostset->count(count_me)" << std::endl; + return 1; + } + if(boostmultiset->count(count_me) != typename MyBoostMultiSet::size_type(j+1)){ + std::cout << "Error in boostmultiset->count(count_me)" << std::endl; + return 1; + } + } + + delete boostset; + delete stdset; + delete boostmultiset; + delete stdmultiset; + return 0; +} + +template +int set_test_copyable () +{ + typedef typename MyBoostSet::value_type IntType; + const int max = 100; + + try{ + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyBoostSet *boostset = new MyBoostSet; + MyStdSet *stdset = new MyStdSet; + MyBoostMultiSet *boostmultiset = new MyBoostMultiSet; + MyStdMultiSet *stdmultiset = new MyStdMultiSet; + + int i; + for(i = 0; i < max; ++i){ + IntType move_me(i); + boostset->insert(boost::move(move_me)); + stdset->insert(i); + IntType move_me2(i); + boostmultiset->insert(boost::move(move_me2)); + stdmultiset->insert(i); + } + if(!CheckEqualContainers(boostset, stdset)) return 1; + if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1; + + { + //Now, test copy constructor + MyBoostSet boostsetcopy(*boostset); + MyStdSet stdsetcopy(*stdset); + + if(!CheckEqualContainers(&boostsetcopy, &stdsetcopy)) + return 1; + + MyBoostMultiSet boostmsetcopy(*boostmultiset); + MyStdMultiSet stdmsetcopy(*stdmultiset); + + if(!CheckEqualContainers(&boostmsetcopy, &stdmsetcopy)) + return 1; + + //And now assignment + boostsetcopy = *boostset; + stdsetcopy = *stdset; + + if(!CheckEqualContainers(&boostsetcopy, &stdsetcopy)) + return 1; + + boostmsetcopy = *boostmultiset; + stdmsetcopy = *stdmultiset; + + if(!CheckEqualContainers(&boostmsetcopy, &stdmsetcopy)) + return 1; + } + delete boostset; + delete boostmultiset; + } + catch(...){ + throw; + } + return 0; +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif diff --git a/test/slist_test.cpp b/test/slist_test.cpp new file mode 100644 index 0000000..e18f0bb --- /dev/null +++ b/test/slist_test.cpp @@ -0,0 +1,82 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "list_test.hpp" +#include "emplace_test.hpp" + +using namespace boost::container; + +//Explicit instantiation to detect compilation errors +template class boost::container::slist >; + +typedef slist MyList; +typedef slist MyMoveList; +typedef slist MyCopyMoveList; +typedef slist MyCopyList; + +class recursive_slist +{ +public: + int id_; + slist slist_; + recursive_slist &operator=(const recursive_slist &o) + { slist_ = o.slist_; return *this; } +}; + +void recursive_slist_test()//Test for recursive types +{ + slist recursive_list_list; +} + +int main () +{ + recursive_slist_test(); + { + //Now test move semantics + slist original; + slist move_ctor(boost::move(original)); + slist move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + { + slist recursive, copy; + //Test to test both move emulations + if(!copy.size()){ + copy = recursive; + } + } + } + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + const test::EmplaceOptions Options = (test::EmplaceOptions) + (test::EMPLACE_FRONT | test::EMPLACE_AFTER | test::EMPLACE_BEFORE | test::EMPLACE_AFTER); + + if(!boost::container::test::test_emplace + < slist, Options>()) + return 1; +} + +#include + diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp new file mode 100644 index 0000000..bf42978 --- /dev/null +++ b/test/stable_vector_test.cpp @@ -0,0 +1,86 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#include +#include "check_equal_containers.hpp" +#include "movable_int.hpp" +#include "expand_bwd_test_allocator.hpp" +#include "expand_bwd_test_template.hpp" +#include "dummy_test_allocator.hpp" +#include "vector_test.hpp" + +using namespace boost::container; + +//Explicit instantiation to detect compilation errors +//template class stable_vector >; + +class recursive_vector +{ + public: + int id_; + stable_vector vector_; + recursive_vector &operator=(const recursive_vector &o) + { vector_ = o.vector_; return *this; } +}; + +void recursive_vector_test()//Test for recursive types +{ + stable_vector recursive, copy; + //Test to test both move emulations + if(!copy.size()){ + copy = recursive; + } +} + +int main() +{ + recursive_vector_test(); + { + //Now test move semantics + stable_vector original; + stable_vector move_ctor(boost::move(original)); + stable_vector move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + typedef stable_vector MyVector; + typedef stable_vector MyMoveVector; + typedef stable_vector MyCopyMoveVector; + typedef stable_vector MyCopyVector; + + if(test::vector_test()) + return 1; + + if(test::vector_test()) + return 1; + + if(test::vector_test()) + return 1; + + if(test::vector_test()) + return 1; + + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE); + if(!boost::container::test::test_emplace + < stable_vector, Options>()) + return 1; + + return 0; +} + +#include diff --git a/test/string_test.cpp b/test/string_test.cpp new file mode 100644 index 0000000..8c873ce --- /dev/null +++ b/test/string_test.cpp @@ -0,0 +1,293 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dummy_test_allocator.hpp" +#include "check_equal_containers.hpp" +#include "expand_bwd_test_allocator.hpp" +#include "expand_bwd_test_template.hpp" + +using namespace boost::container; + +typedef test::dummy_test_allocator DummyCharAllocator; +typedef basic_string, DummyCharAllocator> DummyString; +typedef test::dummy_test_allocator DummyStringAllocator; +typedef test::dummy_test_allocator DummyWCharAllocator; +typedef basic_string, DummyWCharAllocator> DummyWString; +typedef test::dummy_test_allocator DummyWStringAllocator; + +//Explicit instantiations of container::basic_string +template class basic_string, DummyCharAllocator>; +template class basic_string, DummyWCharAllocator>; +//Explicit instantiation of container::vectors of container::strings +template class vector; +template class vector; + +struct StringEqual +{ + template + bool operator ()(const Str1 &string1, const Str2 &string2) const + { + if(string1.size() != string2.size()) + return false; + return std::char_traits::compare + (string1.c_str(), string2.c_str(), string1.size()) == 0; + } +}; + +//Function to check if both lists are equal +template +bool CheckEqualStringVector(StrVector1 *strvect1, StrVector2 *strvect2) +{ + StringEqual comp; + return std::equal(strvect1->begin(), strvect1->end(), + strvect2->begin(), comp); +} + +template +int string_test() +{ + typedef std::string StdString; + typedef vector StdStringVector; + typedef basic_string BoostString; + typedef vector BoostStringVector; + + const int MaxSize = 100; + + //Create shared memory + { + BoostStringVector *boostStringVect = new BoostStringVector; + StdStringVector *stdStringVect = new StdStringVector; + BoostString auxBoostString; + StdString auxStdString(StdString(auxBoostString.begin(), auxBoostString.end() )); + + CharType buffer [20]; + + //First, push back + for(int i = 0; i < MaxSize; ++i){ + auxBoostString = "String"; + auxStdString = "String"; + std::sprintf(buffer, "%i", i); + auxBoostString += buffer; + auxStdString += buffer; + boostStringVect->push_back(auxBoostString); + stdStringVect->push_back(auxStdString); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)){ + return 1; + } + + //Now push back moving + for(int i = 0; i < MaxSize; ++i){ + auxBoostString = "String"; + auxStdString = "String"; + std::sprintf(buffer, "%i", i); + auxBoostString += buffer; + auxStdString += buffer; + boostStringVect->push_back(boost::move(auxBoostString)); + stdStringVect->push_back(auxStdString); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)){ + return 1; + } + + //push front + for(int i = 0; i < MaxSize; ++i){ + auxBoostString = "String"; + auxStdString = "String"; + std::sprintf(buffer, "%i", i); + auxBoostString += buffer; + auxStdString += buffer; + boostStringVect->insert(boostStringVect->begin(), auxBoostString); + stdStringVect->insert(stdStringVect->begin(), auxStdString); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)){ + return 1; + } + + //Now push front moving + for(int i = 0; i < MaxSize; ++i){ + auxBoostString = "String"; + auxStdString = "String"; + std::sprintf(buffer, "%i", i); + auxBoostString += buffer; + auxStdString += buffer; + boostStringVect->insert(boostStringVect->begin(), boost::move(auxBoostString)); + stdStringVect->insert(stdStringVect->begin(), auxStdString); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)){ + return 1; + } + + //Now test long and short representation swapping + + //Short first + auxBoostString = "String"; + auxStdString = "String"; + BoostString boost_swapper; + StdString std_swapper; + boost_swapper.swap(auxBoostString); + std_swapper.swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + if(!StringEqual()(boost_swapper, std_swapper)) + return 1; + boost_swapper.swap(auxBoostString); + std_swapper.swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + if(!StringEqual()(boost_swapper, std_swapper)) + return 1; + + //Shrink_to_fit + auxBoostString.shrink_to_fit(); + StdString(auxStdString).swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + + //Reserve + shrink_to_fit + auxBoostString.reserve(boost_swapper.size()*2+1); + auxStdString.reserve(std_swapper.size()*2+1); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + + auxBoostString.shrink_to_fit(); + StdString(auxStdString).swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + + //Long string + auxBoostString = "LongLongLongLongLongLongLongLongLongLongLongLongLongString"; + auxStdString = "LongLongLongLongLongLongLongLongLongLongLongLongLongString"; + boost_swapper = BoostString(); + std_swapper = StdString(); + boost_swapper.swap(auxBoostString); + std_swapper.swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + if(!StringEqual()(boost_swapper, std_swapper)) + return 1; + boost_swapper.swap(auxBoostString); + std_swapper.swap(auxStdString); + + //Shrink_to_fit + auxBoostString.shrink_to_fit(); + StdString(auxStdString).swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + + auxBoostString.clear(); + auxStdString.clear(); + auxBoostString.shrink_to_fit(); + StdString(auxStdString).swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + + //No sort + std::sort(boostStringVect->begin(), boostStringVect->end()); + std::sort(stdStringVect->begin(), stdStringVect->end()); + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + const CharType prefix [] = "Prefix"; + const int prefix_size = sizeof(prefix)/sizeof(prefix[0])-1; + const CharType sufix [] = "Suffix"; + + for(int i = 0; i < MaxSize; ++i){ + (*boostStringVect)[i].append(sufix); + (*stdStringVect)[i].append(sufix); + (*boostStringVect)[i].insert((*boostStringVect)[i].begin(), + prefix, prefix + prefix_size); + (*stdStringVect)[i].insert((*stdStringVect)[i].begin(), + prefix, prefix + prefix_size); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + for(int i = 0; i < MaxSize; ++i){ + std::reverse((*boostStringVect)[i].begin(), (*boostStringVect)[i].end()); + std::reverse((*stdStringVect)[i].begin(), (*stdStringVect)[i].end()); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + for(int i = 0; i < MaxSize; ++i){ + std::reverse((*boostStringVect)[i].begin(), (*boostStringVect)[i].end()); + std::reverse((*stdStringVect)[i].begin(), (*stdStringVect)[i].end()); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + for(int i = 0; i < MaxSize; ++i){ + std::sort(boostStringVect->begin(), boostStringVect->end()); + std::sort(stdStringVect->begin(), stdStringVect->end()); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + for(int i = 0; i < MaxSize; ++i){ + (*boostStringVect)[i].replace((*boostStringVect)[i].begin(), + (*boostStringVect)[i].end(), + "String"); + (*stdStringVect)[i].replace((*stdStringVect)[i].begin(), + (*stdStringVect)[i].end(), + "String"); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + boostStringVect->erase(std::unique(boostStringVect->begin(), boostStringVect->end()), + boostStringVect->end()); + stdStringVect->erase(std::unique(stdStringVect->begin(), stdStringVect->end()), + stdStringVect->end()); + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + //When done, delete vector + delete boostStringVect; + delete stdStringVect; + } + return 0; +} + +bool test_expand_bwd() +{ + //Now test all back insertion possibilities + typedef test::expand_bwd_test_allocator + allocator_type; + typedef basic_string, allocator_type> + string_type; + return test::test_all_expand_bwd(); +} + +int main() +{ + if(string_test()){ + return 1; + } + + if(!test_expand_bwd()) + return 1; + + return 0; +} + +#include diff --git a/test/tree_test.cpp b/test/tree_test.cpp new file mode 100644 index 0000000..0df3ac4 --- /dev/null +++ b/test/tree_test.cpp @@ -0,0 +1,233 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include "print_container.hpp" +#include "movable_int.hpp" +#include "dummy_test_allocator.hpp" +#include "set_test.hpp" +#include "map_test.hpp" +#include "emplace_test.hpp" + +using namespace boost::container; + +//Alias standard types +typedef std::set MyStdSet; +typedef std::multiset MyStdMultiSet; +typedef std::map MyStdMap; +typedef std::multimap MyStdMultiMap; + +//Alias non-movable types +typedef set MyBoostSet; +typedef multiset MyBoostMultiSet; +typedef map MyBoostMap; +typedef multimap MyBoostMultiMap; + +//Alias movable types +typedef set MyMovableBoostSet; +typedef multiset MyMovableBoostMultiSet; +typedef map MyMovableBoostMap; +typedef multimap MyMovableBoostMultiMap; +typedef set MyMoveCopyBoostSet; +typedef set MyCopyBoostSet; +typedef multiset MyMoveCopyBoostMultiSet; +typedef multiset MyCopyBoostMultiSet; +typedef map MyMoveCopyBoostMap; +typedef multimap MyMoveCopyBoostMultiMap; +typedef map MyCopyBoostMap; +typedef multimap MyCopyBoostMultiMap; +//Test recursive structures +class recursive_set +{ +public: + int id_; + set set_; + friend bool operator< (const recursive_set &a, const recursive_set &b) + { return a.id_ < b.id_; } +}; + +class recursive_map +{ + public: + int id_; + map map_; + friend bool operator< (const recursive_map &a, const recursive_map &b) + { return a.id_ < b.id_; } +}; + +//Test recursive structures +class recursive_multiset +{ +public: + int id_; + multiset multiset_; + friend bool operator< (const recursive_multiset &a, const recursive_multiset &b) + { return a.id_ < b.id_; } +}; + +class recursive_multimap +{ +public: + int id_; + multimap multimap_; + friend bool operator< (const recursive_multimap &a, const recursive_multimap &b) + { return a.id_ < b.id_; } +}; + +template +void test_move() +{ + //Now test move semantics + C original; + C move_ctor(boost::move(original)); + C move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); +} + +int main () +{ + //Recursive container instantiation + { + set set_; + multiset multiset_; + map map_; + multimap multimap_; + } + //Now test move semantics + { + test_move >(); + test_move >(); + test_move >(); + test_move >(); + } + + //using namespace boost::container::detail; + + if(0 != test::set_test()){ + return 1; + } + + if(0 != test::set_test_copyable()){ + return 1; + } + + if(0 != test::set_test()){ + return 1; + } + + if(0 != test::set_test()){ + return 1; + } + + if(0 != test::set_test_copyable()){ + return 1; + } + + if(0 != test::set_test()){ + return 1; + } + + if(0 != test::set_test_copyable()){ + return 1; + } + + if (0 != test::map_test()){ + return 1; + } + + if(0 != test::map_test_copyable()){ + return 1; + } + +// if (0 != test::map_test()){ +// return 1; +// } + + if (0 != test::map_test()){ + return 1; + } + + if (0 != test::map_test_copyable()){ + return 1; + } + + if (0 != test::map_test()){ + return 1; + } + + if (0 != test::map_test_copyable()){ + return 1; + } + + const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC); + if(!boost::container::test::test_emplace, SetOptions>()) + return 1; + if(!boost::container::test::test_emplace, SetOptions>()) + return 1; + const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR); + if(!boost::container::test::test_emplace, MapOptions>()) + return 1; + if(!boost::container::test::test_emplace, MapOptions>()) + return 1; + + return 0; +} + +#include diff --git a/test/util.hpp b/test/util.hpp new file mode 100644 index 0000000..eea3b00 --- /dev/null +++ b/test/util.hpp @@ -0,0 +1,113 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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) 2001-2003 +// William E. Kempf +// +// 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. William E. Kempf 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_TEST_UTIL_HEADER +#define BOOST_CONTAINER_TEST_UTIL_HEADER + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef DEFAULT_EXECUTION_MONITOR_TYPE +# define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition +#endif + +namespace boost { +namespace container { +namespace test { + +inline void sleep(const boost::posix_time::ptime &xt) +{ + boost::container::container_mutex mx; + boost::container::scoped_lock + lock(mx); + boost::container::container_condition cond; + cond.timed_wait(lock, xt); +} + +inline boost::posix_time::ptime delay(int secs, int msecs=0, int nsecs = 0) +{ + (void)msecs; + using namespace boost::posix_time; + int count = static_cast(double(nsecs)* + (double(time_duration::ticks_per_second())/double(1000000000.0))); + count += static_cast(double(msecs)* + (double(time_duration::ticks_per_second())/double(1000.0))); + boost::posix_time::ptime cur = microsec_clock::universal_time(); + return cur += boost::posix_time::time_duration(0, 0, secs, count); +} + +inline bool in_range(const boost::posix_time::ptime& xt, int secs=1) +{ + boost::posix_time::ptime min = delay(-secs); + boost::posix_time::ptime max = delay(0); + return (xt > min) && (max > xt); +} + +boost::xtime xsecs(int secs) +{ + boost::xtime ret; + boost::xtime_get(&ret, boost::TIME_UTC); + ret.sec += secs; + return ret; +} + +template +class thread_adapter +{ + public: + thread_adapter(void (*func)(void*, P &), void* param1, P ¶m2) + : _func(func), _param1(param1) ,_param2(param2){ } + void operator()() const { _func(_param1, _param2); } + + private: + void (*_func)(void*, P &); + void* _param1; + P& _param2; +}; + +template +struct data +{ + data(int id, int secs=0) + : m_id(id), m_value(-1), m_secs(secs) + {} + int m_id; + int m_value; + int m_secs; +}; + +static int shared_val = 0; +static const int BaseSeconds = 1; + +} //namespace test { +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINER_TEST_UTIL_HEADER diff --git a/test/vector_test.cpp b/test/vector_test.cpp new file mode 100644 index 0000000..9bdc584 --- /dev/null +++ b/test/vector_test.cpp @@ -0,0 +1,127 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#include +#include "check_equal_containers.hpp" +#include "movable_int.hpp" +#include "expand_bwd_test_allocator.hpp" +#include "expand_bwd_test_template.hpp" +#include "dummy_test_allocator.hpp" +#include "vector_test.hpp" + +using namespace boost::container; + +//Explicit instantiation to detect compilation errors +template class boost::container::vector >; + +int test_expand_bwd() +{ + //Now test all back insertion possibilities + + //First raw ints + typedef test::expand_bwd_test_allocator + int_allocator_type; + typedef vector + int_vector; + + if(!test::test_all_expand_bwd()) + return 1; + + //Now user defined wrapped int + typedef test::expand_bwd_test_allocator + int_holder_allocator_type; + typedef vector + int_holder_vector; + + if(!test::test_all_expand_bwd()) + return 1; + + //Now user defined bigger wrapped int + typedef test::expand_bwd_test_allocator + triple_int_holder_allocator_type; + + typedef vector + triple_int_holder_vector; + + if(!test::test_all_expand_bwd()) + return 1; + + return 0; +} + +class recursive_vector +{ + public: + int id_; + vector vector_; +}; + +void recursive_vector_test()//Test for recursive types +{ + vector recursive_vector_vector; +} + +enum Test +{ + zero, one, two, three, four, five, six +}; + + +int main() +{ + recursive_vector_test(); + { + //Now test move semantics + vector original; + vector move_ctor(boost::move(original)); + vector move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + typedef vector MyVector; + typedef vector MyMoveVector; + typedef vector MyCopyMoveVector; + typedef vector MyCopyVector; + typedef vector MyEnumVector; + + + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + if(test_expand_bwd()) + return 1; + + MyEnumVector v; + Test t; + v.push_back(t); + v.push_back(::boost::move(t)); + v.push_back(Test()); + + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE); + if(!boost::container::test::test_emplace + < vector, Options>()) + return 1; + + return 0; +} +#include diff --git a/test/vector_test.hpp b/test/vector_test.hpp new file mode 100644 index 0000000..c57700e --- /dev/null +++ b/test/vector_test.hpp @@ -0,0 +1,253 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "print_container.hpp" +#include "check_equal_containers.hpp" +#include "movable_int.hpp" +#include +#include +#include "emplace_test.hpp" + +namespace boost{ +namespace container { +namespace test{ + +template +bool vector_copyable_only(V1 *, V2 *, boost::container::containers_detail::false_type) +{ + return true; +} + +//Function to check if both sets are equal +template +bool vector_copyable_only(V1 *boostvector, V2 *stdvector, boost::container::containers_detail::true_type) +{ + typedef typename V1::value_type IntType; + std::size_t size = boostvector->size(); + boostvector->insert(boostvector->end(), 50, IntType(1)); + stdvector->insert(stdvector->end(), 50, 1); + if(!test::CheckEqualContainers(boostvector, stdvector)) return false; + + { + IntType move_me(1); + boostvector->insert(boostvector->begin()+size/2, 50, boost::move(move_me)); + stdvector->insert(stdvector->begin()+size/2, 50, 1); + if(!test::CheckEqualContainers(boostvector, stdvector)) return false; + } + { + IntType move_me(2); + boostvector->assign(boostvector->size()/2, boost::move(move_me)); + stdvector->assign(stdvector->size()/2, 2); + if(!test::CheckEqualContainers(boostvector, stdvector)) return false; + } + { + IntType move_me(3); + boostvector->assign(boostvector->size()*3-1, boost::move(move_me)); + stdvector->assign(stdvector->size()*3-1, 3); + if(!test::CheckEqualContainers(boostvector, stdvector)) return false; + } + + { + IntType copy_me(3); + const IntType ccopy_me(3); + boostvector->push_back(copy_me); + stdvector->push_back(int(3)); + boostvector->push_back(ccopy_me); + stdvector->push_back(int(3)); + if(!test::CheckEqualContainers(boostvector, stdvector)) return false; + } + + return true; +} + +template +int vector_test() +{ + typedef std::vector MyStdVector; + typedef typename MyBoostVector::value_type IntType; + const int max = 100; + + { + try{ + MyBoostVector *boostvector = new MyBoostVector; + MyStdVector *stdvector = new MyStdVector; + boostvector->resize(100); + stdvector->resize(100); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->resize(200); + stdvector->resize(200); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->resize(0); + stdvector->resize(0); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + for(int i = 0; i < max; ++i){ + IntType new_int(i); + boostvector->insert(boostvector->end(), boost::move(new_int)); + stdvector->insert(stdvector->end(), i); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + } + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + typename MyBoostVector::iterator boostit(boostvector->begin()); + typename MyStdVector::iterator stdit(stdvector->begin()); + typename MyBoostVector::const_iterator cboostit = boostit; + ++boostit; ++stdit; + boostvector->erase(boostit); + stdvector->erase(stdit); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->erase(boostvector->begin()); + stdvector->erase(stdvector->begin()); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + { + //Initialize values + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType new_int(-1); + BOOST_STATIC_ASSERT((boost::container::test::is_copyable::value == false)); + aux_vect[i] = boost::move(new_int); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + + boostvector->insert(boostvector->end() + ,boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(aux_vect + 50)); + stdvector->insert(stdvector->end(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + for(int i = 0, j = static_cast(boostvector->size()); i < j; ++i){ + boostvector->erase(boostvector->begin()); + stdvector->erase(stdvector->begin()); + } + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + } + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType new_int(-1); + aux_vect[i] = boost::move(new_int); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + boostvector->insert(boostvector->begin() + ,boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(aux_vect + 50)); + stdvector->insert(stdvector->begin(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + } +/* + boostvector->reserve(boostvector->size()*2); + stdvector->reserve(stdvector->size()*2); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; +*/ + boostvector->shrink_to_fit(); + MyStdVector(*stdvector).swap(*stdvector); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->shrink_to_fit(); + MyStdVector(*stdvector).swap(*stdvector); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + IntType push_back_this(1); + boostvector->push_back(boost::move(push_back_this)); + stdvector->push_back(int(1)); + boostvector->push_back(IntType(1)); + stdvector->push_back(int(1)); + + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + if(!vector_copyable_only(boostvector, stdvector + ,containers_detail::bool_::value>())){ + return 1; + } + + boostvector->erase(boostvector->begin()); + stdvector->erase(stdvector->begin()); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + for(int i = 0; i < max; ++i){ + IntType insert_this(i); + boostvector->insert(boostvector->begin(), boost::move(insert_this)); + stdvector->insert(stdvector->begin(), i); + boostvector->insert(boostvector->begin(), IntType(i)); + stdvector->insert(stdvector->begin(), int(i)); + } + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + //Test insertion from list + { + std::list l(50, int(1)); + boostvector->insert(boostvector->begin(), l.begin(), l.end()); + stdvector->insert(stdvector->begin(), l.begin(), l.end()); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + boostvector->assign(l.begin(), l.end()); + stdvector->assign(l.begin(), l.end()); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + } +/* + std::size_t cap = boostvector->capacity(); + boostvector->reserve(cap*2); + stdvector->reserve(cap*2); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + boostvector->resize(0); + stdvector->resize(0); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->resize(cap*2); + stdvector->resize(cap*2); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->clear(); + stdvector->clear(); + boostvector->shrink_to_fit(); + MyStdVector(*stdvector).swap(*stdvector); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->resize(cap*2); + stdvector->resize(cap*2); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; +*/ + + delete stdvector; + delete boostvector; + } + catch(std::exception &ex){ + std::cout << ex.what() << std::endl; + return 1; + } + } + std::cout << std::endl << "Test OK!" << std::endl; + return 0; +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include From 90782d289b157237d161916f9529c308597d86f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 30 Aug 2011 12:23:34 +0000 Subject: [PATCH 04/14] Documentation fixes, added AutoIndex indexes [SVN r74154] --- doc/Jamfile.v2 | 38 +++++++- doc/container.qbk | 48 ++++++---- doc/html/index.html | 110 ---------------------- doc/index.idx | 1 + include/boost/container/stable_vector.hpp | 4 + proj/vc7ide/container.vcproj | 3 + 6 files changed, 73 insertions(+), 131 deletions(-) delete mode 100644 doc/html/index.html create mode 100644 doc/index.idx diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index fa1e3a4..4ddc031 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -10,6 +10,8 @@ import doxygen ; import quickbook ; +using auto-index ; + path-constant images_location : html ; doxygen autodoc @@ -29,10 +31,13 @@ doxygen autodoc \"BOOST_RV_REF_2_TEMPL_ARGS(T,a,b)=T &&\" \\ \"BOOST_RV_REF_3_TEMPL_ARGS(T,a,b,c)=TT &&\" \\ \"BOOST_FWD_REF(a)=a &&\"" - "boost.doxygen.reftitle=Boost.Container Reference" + "boost.doxygen.reftitle=Boost.Container Header Reference" ; -xml container : container.qbk ; +xml container : container.qbk + : + ../../../tools/auto_index/include + ; boostbook standalone : @@ -45,4 +50,33 @@ boostbook standalone pdf:img.src.path=$(images_location)/ autodoc pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html + + # Build requirements go here: + + # on (or off) one turns on (or off) indexing: + on + + # Turns on (or off) auto-index-verbose for diagnostic info. + # This is highly recommended until you have got all the many details correct! + on + + # Choose the indexing method (separately for html and PDF) - see manual. + # Choose indexing method for PDFs: + pdf:off + + # Choose indexing method for html: + html:on + + # Set the name of the script file to use (index.idx is popular): + index.idx + # Commands in the script file should all use RELATIVE PATHS + # otherwise the script will not be portable to other machines. + # Relative paths are normally taken as relative to the location + # of the script file, but we can add a prefix to all + # those relative paths using the feature. + # The path specified by may be either relative or + # absolute, for example the following will get us up to the boost root + # directory for most Boost libraries: + "../../.." + ; diff --git a/doc/container.qbk b/doc/container.qbk index ce33961..a9c4337 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -70,7 +70,7 @@ compiler include path. [section:move_emplace Efficient insertion] Move semantics and placement insertion are two features brought by C++11 containers -that can have a very positive impacto in your C++ applications. Boost.Container implements +that can have a very positive impact in your C++ applications. Boost.Container implements both techniques both for C++11 and C++03 compilers. [section:move_containers Move-aware containers] @@ -82,7 +82,7 @@ movable or default constructible types instead of just copy constructible types. Containers themselves are also movable, with no-throw guarantee if allocator or predicate (if present) copy operations are no-throw. This allows -high performance operations when transfering data between vectors. +high performance operations when transferring data between vectors. Let's see an example: [import ../example/doc_move_containers.cpp] @@ -311,7 +311,7 @@ likely to insert a new element anywhere, you'll be shifting N/2 elements.]] This class does not satisfy the requirements of a Standard Associative Container, since the complexity of insert is O(N) rather than O(log N), but otherwise it is almost a drop-in replacement for set.]] -Following Matt Austerns indications, Andrei Alexandrescu's +Following Matt Austern's indications, Andrei Alexandrescu's [@http://www.bestwebbuys.com/Modern-C-Design-Generic-Programming-and-Design-Patterns-Applied-ISBN-9780201704310?isrc=-rd Modern C++ Design] showed `AssocVector`, a `std::map` drop-in replacement designed in his [@http://loki-lib.sourceforge.net/ Loki] library: @@ -427,12 +427,12 @@ Many C++ container implementors felt C++03 guarantees were too weak and started containers experience supporting stateful allocators, offers the following guarantees: * Allocators are copy-constructed in copy/move constructors -* If possible, asingle allocator is hold to construct `value_type` and this allocator is copy constructed - from the user-supplied allocator object during container's contructor. If the container needs an auxiliary +* If possible, a single allocator is hold to construct `value_type` and this allocator is copy constructed + from the user-supplied allocator object during container's constructor. If the container needs an auxiliary allocator (e.g. a array allocator used by `deque` or `stable_vector`), that allocator is also copy-constructed from the user-supplied allocator when the container is constructed (i.e. it's not constructed on the fly when auxiliary memory is needed). -* Allocators are compared for equality when swapping containers. If allocators dont' compare +* Allocators are compared for equality when swapping containers. If allocators don't compare equal allocators are swapped using an unqualified `swap` call. C++11 further improves stateful allocator support through the @@ -491,8 +491,8 @@ If you need a memory optimized version of `boost::container::vector` funct with an internal buffer of 11/23 bytes (32/64 bit systems) [*without] increasing the usual `sizeof` of the string (3 words). -* `[multi]set/map` containers are size optimized embedding the color bit of the red-black trees into - the parent pointer. +* `[multi]set/map` containers are size optimized embedding the color bit of the red-black tree nodes + in the parent pointer. * `[multi]set/map` containers use no recursive functions so stack problems are avoided. @@ -502,7 +502,8 @@ If you need a memory optimized version of `boost::container::vector` funct [section:boost_container_history Boost.Container history] -[*Boost.Container] is a product of a long development effort that started with the experimental Shmem library, +[*Boost.Container] is a product of a long development effort that started +[@http://lists.boost.org/Archives/boost/2004/11/76263.php in 2004 with the experimental Shmem library], which pioneered the use of standard containers in shared memory. Shmem included modified SGI STL container code tweaked to support non-raw `allocator::pointer` types and stateful allocators. Once reviewed, Shmem was accepted as [@http://www.boost.org/libs/interprocess/ Boost.Interprocess] and this library @@ -525,34 +526,45 @@ collect them containers and build [*Boost.Container], a library targeted to a wi [section:Why_boost_container Why Boost.Container?] -With so many high quality standard library implemenations out there, why would you want to +With so many high quality standard library implementations out there, why would you want to use [*Boost.Container]? There are several reasons for that: * If you have a C++03 compiler, you can have access to C++11 features and have an easy code migration when you change your compiler. * It's compatible with [*Boost.Interprocess] shared memory allocators. * You have extremely useful new containers like `stable_vector` and `flat_[multi]set/map`. -* If you work on multiple plataforms, you'll have a portable behaviour without depending +* If you work on multiple platforms, you'll have a portable behaviour without depending on the std-lib implementation conformance of each platform. Some examples: * Default constructors don't allocate memory at all, which improves performance and usually implies a no-throw guarantee (if predicate's or allocator's default constructor doesn't throw). * Small string optimization for [classref boost::container::basic_string basic_string]. -* New extensions beyond the standard based on user feedbak to improve code performance. +* New extensions beyond the standard based on user feedback to improve code performance. [endsect] [endsect] +[include auto_index_helpers.qbk] +[section:index Indexes] +[named_index class_name Class Index] +[named_index typedef_name Typedef Index] +[named_index function_name Function Index] +[/named_index macro_name Macro Index] +[/index] + +[endsect] + +[xinclude autodoc.xml] [section:acknowledgements_notes Acknowledgements, notes and links] * Original standard container code comes from [@http://www.sgi.com/tech/stl/ SGI STL library], which enhanced the original HP STL code. Most of this code was rewritten for [*Boost.Interprocess] and moved to [*Boost.Intrusive]. `deque` and `string` containers still - have fragments of the original SGI code. Many thanks to Alexander Stepanov, Meng Lee, and David Musser, - Matt Austern, and all HP and SGI STL developers. + have fragments of the original SGI code. Many thanks to Alexander Stepanov, Meng Lee, David Musser, + Matt Austern... and all HP and SGI STL developers. * `flat_[multi]_map/set` containers were originally based on [@http://en.wikipedia.org/wiki/Loki_%28C%2B%2B%29 Loki's] AssocVector class. Code was rewritten and expanded for [*Boost.Interprocess], so thanks to Andrei Alexandrescu. @@ -561,12 +573,12 @@ use [*Boost.Container]? There are several reasons for that: [@http://bannalia.blogspot.com/2008/09/introducing-stablevector.html Joaqu\u00EDn M. L\u00F3pez Mu\u00F1oz], then adapted for [*Boost.Interprocess]. Thanks for such a great container. -* Howard Hinnant's help and experience was essential when implementing move semantics, - improving allocator support and implementing small string optimization. Thanks Howard +* Howard Hinnant's help and advices were essential when implementing move semantics, + improving allocator support or implementing small string optimization. Thanks Howard for your wonderful standard library implementations. * And finally thanks to all Boosters who helped all these years, improving, fixing and - reviewing the library. + reviewing all my libraries. [endsect] @@ -576,5 +588,3 @@ use [*Boost.Container]? There are several reasons for that: and redirected to [*Boost.Container ] via using directives. [endsect] - -[xinclude autodoc.xml] diff --git a/doc/html/index.html b/doc/html/index.html deleted file mode 100644 index c7b0ad5..0000000 --- a/doc/html/index.html +++ /dev/null @@ -1,110 +0,0 @@ - - - -Chapter 1. Boost.Container - - - - - - - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
-
-
Next
- - - - -

Last revised: August 26, 2011 at 17:45:38 GMT

-
-
Next
- - diff --git a/doc/index.idx b/doc/index.idx new file mode 100644 index 0000000..9d0d126 --- /dev/null +++ b/doc/index.idx @@ -0,0 +1 @@ +!scan-path "boost/container" ".*.hpp" false diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index eb58007..1886e29 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -335,6 +335,8 @@ struct select_multiallocation_chain } //namespace stable_vector_detail +#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING) #define STABLE_VECTOR_CHECK_INVARIANT \ @@ -346,6 +348,8 @@ BOOST_JOIN(check_invariant_,__LINE__).touch(); #endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING) +#endif //#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + /// @endcond //!Originally developed by Joaquin M. Lopez Munoz, stable_vector is std::vector diff --git a/proj/vc7ide/container.vcproj b/proj/vc7ide/container.vcproj index 188564b..500b5ca 100644 --- a/proj/vc7ide/container.vcproj +++ b/proj/vc7ide/container.vcproj @@ -180,6 +180,9 @@ + + From ceb150731868618f08e98fa51012395d8fd6e32d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 30 Aug 2011 12:50:33 +0000 Subject: [PATCH 05/14] Fixed bug in vector's constructor [SVN r74155] --- include/boost/container/vector.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 22e198a..3930b98 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -459,6 +459,9 @@ class vector : private containers_detail::vector_alloc_holder containers_detail::default_construct_aux_proxy proxy(n); proxy.uninitialized_copy_all_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(); } From 52470831841974e2d47302526c8b5cc808162a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 6 Sep 2011 11:43:41 +0000 Subject: [PATCH 06/14] Fixed error with input_iterator insertion [SVN r74259] --- include/boost/container/vector.hpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 3930b98..be1a222 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -1320,12 +1320,20 @@ class vector : private containers_detail::vector_alloc_holder } template - void priv_range_insert(pointer pos, FwdIt first, FwdIt last, std::forward_iterator_tag) + void priv_range_insert(const_iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag) { if(first != last){ const size_type n = std::distance(first, last); containers_detail::advanced_insert_aux_proxy proxy(first, last); - priv_range_insert(pos, n, proxy); + priv_range_insert(pos.get_ptr(), n, proxy); + } + } + + template + void priv_range_insert(const_iterator pos, InIt first, InIt last, std::input_iterator_tag) + { + for(;first != last; ++first){ + this->emplace(pos, *first); } } @@ -1755,14 +1763,6 @@ class vector : private containers_detail::vector_alloc_holder } } - template - void priv_range_insert(const_iterator pos, InIt first, InIt last, std::input_iterator_tag) - { - for(;first != last; ++first){ - this->insert(pos, ::boost::move(value_type(*first))); - } - } - template void priv_assign_aux(InIt first, InIt last, std::input_iterator_tag) { @@ -1925,7 +1925,7 @@ class vector : private containers_detail::vector_alloc_holder { //Dispatch depending on integer/iterator typedef typename std::iterator_traits::iterator_category ItCat; - this->priv_range_insert(pos.get_ptr(), first, last, ItCat()); + this->priv_range_insert(pos, first, last, ItCat()); } void priv_check_range(size_type n) const From 935a534713051dcb886caa3d1a4ee1d42e7dfcac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 22 Dec 2011 20:08:24 +0000 Subject: [PATCH 07/14] Introducing allocator_traits and pointer_traits changes into several libraries. [SVN r76106] --- .../container/allocator/allocator_traits.hpp | 381 ++++++++++ .../boost/container/allocator/memory_util.hpp | 77 ++ .../container/allocator/scoped_allocator.hpp | 651 +++++++++++++++++ include/boost/container/container_fwd.hpp | 8 +- include/boost/container/deque.hpp | 570 +++++++++------ .../detail/adaptive_node_pool_impl.hpp | 20 +- .../container/detail/advanced_insert_int.hpp | 469 +++++++------ include/boost/container/detail/algorithms.hpp | 84 +-- .../container/detail/allocation_type.hpp | 6 +- .../boost/container/detail/config_begin.hpp | 8 +- include/boost/container/detail/config_end.hpp | 4 +- include/boost/container/detail/destroyers.hpp | 85 ++- include/boost/container/detail/flat_tree.hpp | 190 +++-- .../container/detail/function_detector.hpp | 88 +++ include/boost/container/detail/iterators.hpp | 70 +- .../boost/container/detail/math_functions.hpp | 4 +- include/boost/container/detail/mpl.hpp | 11 +- .../detail/multiallocation_chain.hpp | 30 +- .../container/detail/node_alloc_holder.hpp | 301 ++++---- .../boost/container/detail/node_pool_impl.hpp | 12 +- include/boost/container/detail/pair.hpp | 32 +- .../boost/container/detail/pool_common.hpp | 4 +- .../boost/container/detail/preprocessor.hpp | 165 +++-- include/boost/container/detail/stored_ref.hpp | 10 +- .../container/detail/transform_iterator.hpp | 8 +- include/boost/container/detail/tree.hpp | 330 +++++---- .../boost/container/detail/type_traits.hpp | 10 +- include/boost/container/detail/utilities.hpp | 203 ++++-- include/boost/container/detail/value_init.hpp | 12 +- .../detail/variadic_templates_tools.hpp | 10 +- .../boost/container/detail/version_type.hpp | 16 +- include/boost/container/detail/workaround.hpp | 17 +- include/boost/container/flat_map.hpp | 470 +++++++------ include/boost/container/flat_set.hpp | 105 +-- include/boost/container/list.hpp | 252 +++---- include/boost/container/map.hpp | 190 ++--- include/boost/container/set.hpp | 111 +-- include/boost/container/slist.hpp | 226 +++--- include/boost/container/stable_vector.hpp | 467 +++++++----- include/boost/container/string.hpp | 381 ++++++---- include/boost/container/vector.hpp | 664 +++++++++--------- 41 files changed, 4304 insertions(+), 2448 deletions(-) create mode 100644 include/boost/container/allocator/allocator_traits.hpp create mode 100644 include/boost/container/allocator/memory_util.hpp create mode 100644 include/boost/container/allocator/scoped_allocator.hpp create mode 100644 include/boost/container/detail/function_detector.hpp diff --git a/include/boost/container/allocator/allocator_traits.hpp b/include/boost/container/allocator/allocator_traits.hpp new file mode 100644 index 0000000..34f526e --- /dev/null +++ b/include/boost/container/allocator/allocator_traits.hpp @@ -0,0 +1,381 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Pablo Halpern 2009. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP +#define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include //numeric_limits<>::max() +#include //placement new +#include //std::allocator +#include + +///@cond + +namespace boost { +namespace container { +namespace container_detail { + +//workaround needed for C++03 compilers with no construct() +//supporting rvalue references +template +struct is_std_allocator +{ static const bool value = false; }; + +template +struct is_std_allocator< std::allocator > +{ static const bool value = true; }; + +} //namespace container_detail { + +///@endcond + +template +struct allocator_traits +{ + //allocator_type + typedef Alloc allocator_type; + //value_type + typedef typename Alloc::value_type value_type; + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //!Alloc::pointer if such a type exists; otherwise, value_type* + //! + typedef unspecified pointer; + //!Alloc::const_pointer if such a type exists ; otherwise, pointer_traits::rebind::rebind. + //! + typedef unspecified void_pointer; + //!Alloc::const_void_pointer if such a type exists ; otherwis e, pointer_traits::rebind::difference_type. + //! + typedef unspecified difference_type; + //!Alloc::size_type if such a type exists ; otherwise, make_unsigned::type + //! + typedef unspecified 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; + //!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; + //!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; + //!Defines an allocator: Alloc::rebind::other if such a type exists; otherwise, Alloc + //!if Alloc is a class template instantiation of the form Alloc, 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 + //!deduced by previously detailed rules. + template using rebind_alloc = unspecified; + + //!In C++03 compilers
rebind_traits
is a struct derived from + //!
allocator_traits
, where `OtherAlloc` is
+      //!the allocator deduced by rules explained in `rebind_alloc`.
+      template  using rebind_traits = allocator_traits >;
+
+      //!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`.
+      template 
+      struct portable_rebind_alloc
+      {  typedef unspecified_type type;  };
+   #else
+      //pointer
+      typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
+         pointer, value_type*)
+            pointer;
+      //const_pointer
+      typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 
+         const_pointer, typename boost::intrusive::pointer_traits::template
+            rebind_pointer::type)
+               const_pointer;
+      //reference
+      typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
+         reference, value_type&)
+            reference;
+      //const_reference
+      typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 
+         const_reference, const value_type&)
+               const_reference;
+      //void_pointer
+      typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 
+         void_pointer, typename boost::intrusive::pointer_traits::template
+            rebind_pointer::type)
+               void_pointer;
+      //const_void_pointer
+      typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
+         const_void_pointer, typename boost::intrusive::pointer_traits::template
+            rebind_pointer::type)
+               const_void_pointer;
+      //difference_type
+      typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
+         difference_type, std::ptrdiff_t)
+            difference_type;
+      //size_type
+      typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
+         size_type, std::size_t)
+            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;
+      //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;
+      //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;
+
+      #if !defined(BOOST_NO_TEMPLATE_ALIASES)
+         //C++11
+         template  using rebind_alloc  = boost::intrusive::detail::type_rebinder::type;
+         template  using rebind_traits = allocator_traits< rebind_alloc >;
+      #else    //!defined(BOOST_NO_TEMPLATE_ALIASES)
+         //Some workaround for C++03 or C++11 compilers with no template aliases
+         template 
+         struct rebind_alloc : boost::intrusive::detail::type_rebinder::type
+         {
+            typedef typename boost::intrusive::detail::type_rebinder::type Base;
+            #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+            template 
+            rebind_alloc(Args&&... args)
+               : Base(boost::forward(args)...)
+            {}
+            #else    //!defined(BOOST_NO_VARIADIC_TEMPLATES)
+            #define BOOST_PP_LOCAL_MACRO(n)                                                        \
+            BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+            rebind_alloc(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                       \
+               : Base(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))                       \
+            {}                                                                                     \
+            //
+            #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+            #include BOOST_PP_LOCAL_ITERATE()
+            #endif   //!defined(BOOST_NO_VARIADIC_TEMPLATES)
+         };
+
+         template 
+         struct rebind_traits
+            : allocator_traits::type>
+         {};
+      #endif   //!defined(BOOST_NO_TEMPLATE_ALIASES)
+      template 
+      struct portable_rebind_alloc
+      {  typedef typename boost::intrusive::detail::type_rebinder::type type;  };
+   #endif   //BOOST_CONTAINER_DOXYGEN_INVOKED
+
+   //!Returns: a.allocate(n)
+   //!
+   static pointer allocate(Alloc &a, size_type n)
+   {  return a.allocate(n);  }
+
+   //!Returns: a.deallocate(p, n)
+   //!
+   //!Throws: Nothing
+   static void deallocate(Alloc &a, pointer p, size_type n)
+   {  return a.deallocate(p, n);  }
+
+   //!Effects: calls `a.construct(p, std::forward(args)...)` if that call is well-formed;
+   //!otherwise, invokes `::new (static_cast(p)) T(std::forward(args)...)`
+   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
+            ::value;
+      ::boost::integral_constant flag;
+      return allocator_traits::priv_allocate(flag, a, n, p);
+   }
+
+   //!Effects: calls a.destroy(p) if that call is well-formed;
+   //!otherwise, invokes `p->~T()`.
+   template
+   static void destroy(Alloc &a, T*p)
+   {
+      typedef T* destroy_pointer;
+      const bool value = boost::container::container_detail::
+         has_member_function_callable_with_destroy
+            ::value;
+      ::boost::integral_constant flag;
+      allocator_traits::priv_destroy(flag, a, p);
+   }
+
+   //!Returns: a.max_size() if that expression is well-formed; otherwise,
+   //!`numeric_limits::max()`.
+   static size_type max_size(const Alloc &a)
+   {
+      const bool value = boost::container::container_detail::
+         has_member_function_callable_with_max_size
+            ::value;
+      ::boost::integral_constant flag;
+      return allocator_traits::priv_max_size(flag, a);
+   }
+
+   //!Returns: a.select_on_container_copy_construction() if that expres sion is well- formed;
+   //!otherwise, a.
+   static Alloc 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
+            ::value;
+      ::boost::integral_constant flag;
+      return allocator_traits::priv_select_on_container_copy_construction(flag, a);
+   }
+
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+      //!Effects: calls a.construct(p, std::forward(args)...) if that call is well-formed; 
+      //!otherwise, invokes `::new (static_cast(p)) T(std::forward(args)...)`
+      template 
+      static void construct(Alloc & a, T* p, Args&&... args)
+      {
+         ::boost::integral_constant::value> flag;
+         allocator_traits::priv_construct(flag, a, p, ::boost::forward(args)...);
+      }
+   #endif
+
+   #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+      private:
+      static pointer priv_allocate(boost::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)
+      {  return allocator_traits::allocate(a, n);  }
+
+      template
+      static void priv_destroy(boost::true_type, Alloc &a, T* p)
+      {  a.destroy(p);  }
+
+      template
+      static void priv_destroy(boost::false_type, Alloc &, T* p)
+      {  p->~T(); (void)p;  }
+
+      static size_type priv_max_size(boost::true_type, const Alloc &a)
+      {  return a.max_size();  }
+
+      static size_type priv_max_size(boost::false_type, const Alloc &)
+      {  return (std::numeric_limits::max)();  }
+
+      static Alloc priv_select_on_container_copy_construction(boost::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)
+      {  return a;  }
+
+      #if defined(BOOST_CONTAINER_PERFECT_FORWARDING)
+         template
+         static void priv_construct(boost::false_type, Alloc &a, T *p, Args && ...args)                    
+         {                                                                                                  
+            const bool value = boost::container::container_detail::
+                  has_member_function_callable_with_construct
+                     < Alloc, T*, Args... >::value;
+            ::boost::integral_constant flag;
+            priv_construct_dispatch2(flag, a, p, ::boost::forward(args)...);
+         }
+
+         template
+         static void priv_construct(boost::true_type, Alloc &a, T *p, Args && ...args)
+         {
+            priv_construct_dispatch2(boost::false_type(), a, p, ::boost::forward(args)...);
+         }
+
+         template
+         static void priv_construct_dispatch2(boost::true_type, Alloc &a, T *p, Args && ...args)
+         {  a.construct( p, ::boost::forward(args)...);  }
+
+         template
+         static void priv_construct_dispatch2(boost::false_type, Alloc &, T *p, Args && ...args)
+         {  ::new((void*)p) T(::boost::forward(args)...); }
+      #else
+         public:
+         #define BOOST_PP_LOCAL_MACRO(n)                                                              \
+         template                                 \
+         static void construct(Alloc &a, T *p                                                         \
+                              BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _))            \
+         {                                                                                            \
+            ::boost::integral_constant::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                                      \
+         static void priv_construct(boost::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 flag;                                                   \
+            priv_construct_dispatch2(flag, a, p                                                             \
+               BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) );                            \
+         }                                                                                                  \
+                                                                                                            \
+         template                                      \
+         static void priv_construct(boost::true_type, Alloc &a, T *p                                        \
+                        BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_))                         \
+         {                                                                                                  \
+            priv_construct_dispatch2(boost::false_type(), a, p                                              \
+               BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) );                            \
+         }                                                                                                  \
+                                                                                                            \
+         template                                      \
+         static void priv_construct_dispatch2(boost::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                                      \
+         static void priv_construct_dispatch2(boost::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, _)); }                     \
+         //
+         #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+         #include BOOST_PP_LOCAL_ITERATE()
+      #endif   //BOOST_CONTAINER_PERFECT_FORWARDING
+   #endif   //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+   ///@endcond
+};
+
+}  //namespace container {
+}  //namespace boost {
+
+#include 
+
+#endif // ! defined(BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP)
diff --git a/include/boost/container/allocator/memory_util.hpp b/include/boost/container/allocator/memory_util.hpp
new file mode 100644
index 0000000..f9cc70a
--- /dev/null
+++ b/include/boost/container/allocator/memory_util.hpp
@@ -0,0 +1,77 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP
+#define BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include 
+#include 
+#include 
+#include 
+
+
+#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, ))
+#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, ))
+#include BOOST_PP_ITERATE()
+
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME max_size
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END   }}}
+#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, ))
+#include BOOST_PP_ITERATE()
+
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME select_on_container_copy_construction
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END   }}}
+#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, ))
+#include BOOST_PP_ITERATE()
+
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME construct
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END   }}}
+#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, ))
+#include BOOST_PP_ITERATE()
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer);
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_pointer);
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference);
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reference);
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(void_pointer);
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_void_pointer);
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(size_type);
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type);
+
+}  //namespace container_detail {
+}  //namespace container {
+}  //namespace boost {
+
+#include 
+
+#endif // ! defined(BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP)
diff --git a/include/boost/container/allocator/scoped_allocator.hpp b/include/boost/container/allocator/scoped_allocator.hpp
new file mode 100644
index 0000000..03e12d1
--- /dev/null
+++ b/include/boost/container/allocator/scoped_allocator.hpp
@@ -0,0 +1,651 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Pablo Halpern 2009. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
+#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+namespace boost { namespace container {
+
+template 
+class scoped_allocator_adaptor;
+
+template 
+scoped_allocator_adaptor make_scoped();
+
+template 
+class scoped_allocator_adaptor_base : public OuterAlloc
+{
+    typedef allocator_traits OuterTraits;
+
+public:
+    // Workaround for inability of gcc-4.4.1 to expand InnerAllocs...
+//    typedef scoped_allocator_adaptor inner_allocator_type;
+    typedef decltype(make_scoped()) inner_allocator_type;
+
+    scoped_allocator_adaptor_base();
+
+    template 
+      scoped_allocator_adaptor_base(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs);
+
+    template 
+      scoped_allocator_adaptor_base(const scoped_allocator_adaptor& other);
+    template 
+      scoped_allocator_adaptor_base(scoped_allocator_adaptor&& other);
+    
+    inner_allocator_type&       inner_allocator()
+        { return _M_inner_allocs; }
+    inner_allocator_type const& inner_allocator() const
+        { return _M_inner_allocs; }
+
+    // Allocator propagation functions.
+    scoped_allocator_adaptor
+    select_on_container_copy_construction() const;
+
+    typedef std::integral_constant<
+        bool,
+        OuterTraits::propagate_on_container_copy_assignment::value ||
+        inner_allocator_type::propagate_on_container_copy_assignment::value
+        > propagate_on_container_copy_assignment;
+    typedef std::integral_constant<
+        bool,
+        OuterTraits::propagate_on_container_move_assignment::value ||
+        inner_allocator_type::propagate_on_container_move_assignment::value
+        > propagate_on_container_move_assignment;
+    typedef std::integral_constant<
+        bool,
+        OuterTraits::propagate_on_container_swap::value ||
+        inner_allocator_type::propagate_on_container_swap::value
+        > propagate_on_container_swap;
+
+private:
+    inner_allocator_type _M_inner_allocs;
+};
+
+// Specialization with only one parameter.
+template 
+class scoped_allocator_adaptor_base : public OuterAlloc
+{
+    typedef allocator_traits OuterTraits;
+public:
+    typedef scoped_allocator_adaptor inner_allocator_type;
+
+    scoped_allocator_adaptor_base();
+
+    template 
+      scoped_allocator_adaptor_base(OuterA2&& outerAlloc);
+
+    template 
+      scoped_allocator_adaptor_base(const scoped_allocator_adaptor& other);
+    template 
+      scoped_allocator_adaptor_base(scoped_allocator_adaptor&& other);
+    
+    inner_allocator_type&       inner_allocator()
+        { return static_cast(*this); }
+
+    inner_allocator_type const& inner_allocator() const
+        { return static_cast(*this); }
+
+    // Allocator propagation functions.
+    scoped_allocator_adaptor
+      select_on_container_copy_construction() const;
+
+    typedef typename OuterTraits::propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
+    typedef typename OuterTraits::propagate_on_container_move_assignment propagate_on_container_move_assignment;
+    typedef typename OuterTraits::propagate_on_container_swap propagate_on_container_swap;
+};
+
+template 
+class scoped_allocator_adaptor
+    : public scoped_allocator_adaptor_base
+{
+    typedef scoped_allocator_adaptor_base _Base;
+    typedef allocator_traits                              _Traits;
+
+public:
+    typedef OuterAlloc                           outer_allocator_type;
+    typedef typename _Base::inner_allocator_type inner_allocator_type;
+    
+    typedef typename allocator_traits::size_type          size_type;
+    typedef typename allocator_traits::difference_type    difference_type;
+    typedef typename allocator_traits::pointer            pointer;
+    typedef typename allocator_traits::const_pointer      const_pointer;
+    typedef typename allocator_traits::void_pointer       void_pointer;
+    typedef typename allocator_traits::const_void_pointer const_void_pointer;
+    typedef typename allocator_traits::value_type          value_type;
+
+    template 
+    struct rebind {
+        typedef typename allocator_traits::template rebind_traits rebound_traits;
+        typedef typename rebound_traits::allocator_type rebound_outer; // exposition only
+        typedef scoped_allocator_adaptor other;
+    };
+
+    scoped_allocator_adaptor();
+    scoped_allocator_adaptor(const scoped_allocator_adaptor& other);
+
+    template 
+      scoped_allocator_adaptor(const scoped_allocator_adaptor& other);
+    template 
+      scoped_allocator_adaptor(scoped_allocator_adaptor&& other);
+    
+    template 
+      scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs);
+
+    ~scoped_allocator_adaptor();
+
+    inner_allocator_type      & inner_allocator()
+        { return _Base::inner_allocator(); }
+    inner_allocator_type const& inner_allocator() const
+        { return _Base::inner_allocator(); }
+    outer_allocator_type      & outer_allocator()
+        { return *this; }
+    outer_allocator_type const& outer_allocator() const
+        { return *this; }
+
+    pointer allocate(size_type n);
+    pointer allocate(size_type n, const_void_pointer hint);
+    void deallocate(pointer p, size_type n);
+    size_type max_size() const;
+
+    template 
+      void construct(T* p, Args&&... args);
+
+    // Specializations to pass inner_allocator to pair::first and pair::second
+    template 
+      void construct(std::pair* p);
+    template 
+      void construct(std::pair* p, U&& x, V&& y);
+    template 
+      void construct(std::pair* p, const std::pair& pr);
+    template 
+      void construct(std::pair* p, std::pair&& pr);
+
+    template 
+      void destroy(T* p);
+};
+
+template 
+inline
+bool operator==(const scoped_allocator_adaptor& a,
+                const scoped_allocator_adaptor& b);
+
+template 
+inline
+bool operator!=(const scoped_allocator_adaptor& a,
+                const scoped_allocator_adaptor& b);
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation of scoped_allocator_adaptor_base
+///////////////////////////////////////////////////////////////////////////////
+
+template 
+inline
+scoped_allocator_adaptor_base::
+    scoped_allocator_adaptor_base()
+{
+}
+
+template 
+  template 
+    scoped_allocator_adaptor_base::
+      scoped_allocator_adaptor_base(OuterA2&&        outerAlloc,
+                                    const InnerAllocs&... innerAllocs)
+          : OuterAlloc(std::forward(outerAlloc))
+          , _M_inner_allocs(innerAllocs...)
+{
+}
+
+template 
+  template 
+    scoped_allocator_adaptor_base::
+      scoped_allocator_adaptor_base(
+          const scoped_allocator_adaptor& other)
+          : OuterAlloc(other.outer_allocator())
+          , _M_inner_allocs(other.inner_allocator())
+{
+}
+
+template 
+  template 
+    scoped_allocator_adaptor_base::
+      scoped_allocator_adaptor_base(
+          scoped_allocator_adaptor&& other)
+          : OuterAlloc(std::move(other.outer_allocator()))
+          , _M_inner_allocs(std::move(other.inner_allocator()))
+{
+}
+
+template 
+inline
+scoped_allocator_adaptor
+scoped_allocator_adaptor_base::
+  select_on_container_copy_construction() const
+{
+    return scoped_allocator_adaptor(
+        allocator_traits::select_on_container_copy_construction(
+            this->outer_allocator()),
+        allocator_traits::select_on_container_copy_construction(
+            this->inner_allocator()));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation of scoped_allocator_adaptor_base specialization
+///////////////////////////////////////////////////////////////////////////////
+
+template 
+inline
+scoped_allocator_adaptor_base::
+    scoped_allocator_adaptor_base()
+{
+}
+
+template 
+  template 
+    scoped_allocator_adaptor_base::
+     scoped_allocator_adaptor_base(OuterA2&& outerAlloc)
+         : OuterAlloc(std::forward(outerAlloc))
+{
+}
+
+template 
+  template 
+    scoped_allocator_adaptor_base::
+      scoped_allocator_adaptor_base(
+          const scoped_allocator_adaptor& other)
+          : OuterAlloc(other.outer_allocator())
+{
+}
+
+template 
+  template 
+    scoped_allocator_adaptor_base::
+      scoped_allocator_adaptor_base(
+          scoped_allocator_adaptor&& other)
+          : OuterAlloc(std::move(other.outer_allocator()))
+{
+}
+
+// template 
+// inline
+// scoped_allocator_adaptor& 
+// scoped_allocator_adaptor_base::inner_allocator()
+// {
+//     return *this;
+// }
+
+// template 
+// inline
+// scoped_allocator_adaptor const& 
+// scoped_allocator_adaptor_base::inner_allocator() cosnt
+// {
+//     return *this;
+// }
+
+template 
+inline
+scoped_allocator_adaptor
+scoped_allocator_adaptor_base::
+select_on_container_copy_construction() const
+{
+    return
+        allocator_traits::select_on_container_copy_construction(
+            this->outer_allocator());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation of scoped_allocator_adaptor details
+///////////////////////////////////////////////////////////////////////////////
+
+namespace __details {
+
+    // Overload resolution for __has_ctor resolves to this function
+    // when _Tp is constructible with _Args.  Returns true_type().
+    
+    static void* __void_p; // Declared but not defined
+
+    template 
+    inline
+    auto __has_ctor(int, _Args&&... __args) ->
+        decltype((new (__void_p) _Tp(__args...), std::true_type()))
+        { return std::true_type(); }
+
+    // Overload resolution for __has_ctor resolves to this function
+    // when _Tp is not constructible with _Args. Returns false_type().
+    template 
+    auto __has_ctor(_LowPriorityConversion, _Args&&...) ->
+        std::false_type
+        { return std::false_type(); }
+
+    template 
+    struct __is_scoped_allocator_imp {
+        template 
+        static char test(int, typename T::outer_allocator_type*);
+        template 
+        static int test(_LowPriorityConversion, void*);
+        static const bool value = (1 == sizeof(test<_Alloc>(0, 0)));
+    };
+
+    template 
+    struct __is_scoped_allocator
+        : std::integral_constant::value>
+    {
+    };
+
+#if 0
+    // Called when outer_allocator_type is not a scoped allocator
+    // (recursion stop).
+    template 
+    inline
+    auto __outermost_alloc(_LowPriorityConversion, _Alloc& __a) ->
+        _Alloc&
+    {
+        return __a;
+    }
+
+    // Called when outer_allocator_type is a scoped allocator to
+    // return the outermost allocator type.
+    template 
+    inline auto __outermost_alloc(int, _Alloc& __a) ->
+        decltype(__outermost_alloc(0,__a.outer_allocator())) 
+    {
+        return __a.outer_allocator();
+    }
+#endif
+
+    template 
+    inline void __dispatch_scoped_construct(std::false_type __uses_alloc,
+                                            _Ignore         __use_alloc_prefix,
+                                            _OuterAlloc&    __outer_alloc,
+                                            _InnerAlloc&    __inner_alloc,
+                                            _Tp* __p, _Args&&... __args)
+    {
+        // _Tp doesn't use allocators.  Construct without an
+        // allocator argument.
+        allocator_traits<_OuterAlloc>::construct(__outer_alloc, __p,
+                                               std::forward<_Args>(__args)...);
+    }
+
+    template 
+    inline void __dispatch_scoped_construct(std::true_type  __uses_alloc,
+                                            std::true_type  __use_alloc_prefix,
+                                            _OuterAlloc&    __outer_alloc,
+                                            _InnerAlloc&    __inner_alloc,
+                                            _Tp* __p, _Args&&... __args)
+    {
+        // _Tp doesn't use allocators.  Construct without an
+        // allocator argument.
+        allocator_traits<_OuterAlloc>::construct(__outer_alloc, __p,
+                                                 allocator_arg, __inner_alloc,
+                                               std::forward<_Args>(__args)...);
+    }
+
+    template 
+    inline void __dispatch_scoped_construct(std::true_type  __uses_alloc,
+                                            std::false_type __use_alloc_prefix,
+                                            _OuterAlloc&    __outer_alloc,
+                                            _InnerAlloc&    __inner_alloc,
+                                            _Tp* __p, _Args&&... __args)
+    {
+        // If _Tp uses an allocator compatible with _InnerAlloc,
+        // but the specific constructor does not have a variant that
+        // takes an allocator argument, then program is malformed.
+//         static_assert(has_constructor<_Tp, _Args...>::value,
+//                       "Cannot pass inner allocator to this constructor");
+
+        allocator_traits<_OuterAlloc>::construct(
+            __outer_alloc, __p, std::forward<_Args>(__args)...,
+            __inner_alloc);
+    }
+
+    template 
+    inline void __do_scoped_construct(std::false_type __scoped_outer,
+                                      _OuterAlloc&    __outer_alloc,
+                                      _InnerAlloc&    __inner_alloc,
+                                      _Tp* __p, _Args&&... __args)
+    {
+        // Dispatch construction to the correct __dispatch_scoped_construct()
+        // function based on whether _Tp uses an allocator of type
+        // _InnerAlloc and, if so, whether there exists the following
+        // constructor:
+        //   _Tp(allocator_arg_t, _InnerAlloc, Args...).
+        auto __uses_alloc = uses_allocator<_Tp, _InnerAlloc>();
+        auto __use_alloc_prefix = __has_ctor<_Tp>(0, allocator_arg,
+                                               __inner_alloc,
+                                               std::forward<_Args>(__args)...);
+        __dispatch_scoped_construct(__uses_alloc, __use_alloc_prefix,
+                                    __outer_alloc,
+                                    __inner_alloc,
+                                    __p, std::forward<_Args>(__args)...);
+    }
+
+    template 
+    void __do_scoped_construct(std::true_type  __scoped_outer,
+                               _OuterAlloc&    __outer_alloc,
+                               _InnerAlloc&    __inner_alloc,
+                               _Tp* __p, _Args&&... __args)
+    {
+        // Use outermost allocator if __outer_alloc is scoped
+        typedef typename _OuterAlloc::outer_allocator_type outerouter;
+        __do_scoped_construct(__is_scoped_allocator(),
+                              __outer_alloc.outer_allocator(),
+                              __inner_alloc,
+                              __p, std::forward<_Args>(__args)...);
+    }
+
+} // end namespace __details
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation of scoped_allocator_adaptor
+///////////////////////////////////////////////////////////////////////////////
+
+template 
+scoped_allocator_adaptor::
+    scoped_allocator_adaptor()
+{
+}
+
+template 
+scoped_allocator_adaptor::
+    scoped_allocator_adaptor(const scoped_allocator_adaptor& other)
+        : _Base(other)
+{
+}
+
+template 
+  template 
+    scoped_allocator_adaptor::
+      scoped_allocator_adaptor(const scoped_allocator_adaptor& other)
+        : _Base(other)
+{
+}
+
+template 
+  template 
+    scoped_allocator_adaptor::
+      scoped_allocator_adaptor(scoped_allocator_adaptor&& other)
+          : _Base(std::move(other))
+{
+}
+    
+template 
+  template 
+    scoped_allocator_adaptor::
+      scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs)
+          : _Base(std::forward(outerAlloc), innerAllocs...)
+{
+}
+
+template 
+scoped_allocator_adaptor::
+    ~scoped_allocator_adaptor()
+{
+}
+
+template 
+inline typename allocator_traits::pointer
+scoped_allocator_adaptor::
+    allocate(size_type n)
+{
+    return allocator_traits::allocate(outer_allocator(), n);
+}
+
+template 
+inline typename allocator_traits::pointer
+scoped_allocator_adaptor::
+    allocate(size_type n, const_void_pointer hint)
+{
+    return allocator_traits::allocate(outer_allocator(), n, hint);
+}
+
+template 
+inline void scoped_allocator_adaptor::
+    deallocate(pointer p, size_type n)
+{
+    allocator_traits::deallocate(outer_allocator(), p, n);
+}
+
+template 
+inline typename allocator_traits::size_type
+scoped_allocator_adaptor::max_size() const
+{
+    return allocator_traits::max_size(outer_allocator());
+}
+
+template 
+  template 
+    inline void scoped_allocator_adaptor::
+    destroy(T* p)
+{
+    allocator_traits::destroy(outer_allocator(), p);
+}
+
+template 
+  template 
+    inline
+    void scoped_allocator_adaptor::construct(T* p,
+                                                             Args&&... args)
+{
+    __do_scoped_construct(__details::__is_scoped_allocator(),
+                          this->outer_allocator(), this->inner_allocator(),
+                          p, std::forward(args)...);
+}
+
+template 
+  template 
+  void scoped_allocator_adaptor::construct(
+      std::pair* p)
+{
+    construct(addressof(p->first));
+    try {
+        construct(addressof(p->second));
+    }
+    catch (...) {
+        destroy(addressof(p->first));
+        throw;
+    }
+}
+
+template 
+  template 
+  void scoped_allocator_adaptor::construct(
+      std::pair* p, U&& x, V&& y)
+{
+    construct(addressof(p->first), std::forward(x));
+    try {
+        construct(addressof(p->second), std::forward(y));
+    }
+    catch (...) {
+        destroy(addressof(p->first));
+        throw;
+    }
+}
+
+template 
+  template 
+  void scoped_allocator_adaptor::construct(
+      std::pair* p, const std::pair& pr)
+{
+    construct(addressof(p->first), pr.first);
+    try {
+        construct(addressof(p->second), pr.second);
+    }
+    catch (...) {
+        destroy(addressof(p->first));
+        throw;
+    }
+}
+
+template 
+  template 
+  void scoped_allocator_adaptor::construct(
+      std::pair* p, std::pair&& pr)
+{
+    construct(addressof(p->first), std::move(pr.first));
+    try {
+        construct(addressof(p->second), std::move(pr.second));
+    }
+    catch (...) {
+        destroy(addressof(p->first));
+        throw;
+    }
+}
+
+template 
+inline
+bool operator==(const scoped_allocator_adaptor& a,
+                const scoped_allocator_adaptor& b)
+{
+    return a.outer_allocator() == b.outer_allocator()
+        && a.inner_allocator() == b.inner_allocator();
+}
+
+template 
+inline
+bool operator==(const scoped_allocator_adaptor& a,
+                const scoped_allocator_adaptor& b)
+{
+    return a.outer_allocator() == b.outer_allocator();
+}
+
+template 
+inline
+bool operator!=(const scoped_allocator_adaptor& a,
+                const scoped_allocator_adaptor& b)
+{
+    return ! (a == b);
+}
+
+}} // namespace boost { namespace container {
+
+#include 
+
+#endif //  BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
diff --git a/include/boost/container/container_fwd.hpp b/include/boost/container/container_fwd.hpp
index f304382..b58ca8e 100644
--- a/include/boost/container/container_fwd.hpp
+++ b/include/boost/container/container_fwd.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_CONTAINERS_FWD_HPP
-#define BOOST_CONTAINERS_CONTAINERS_FWD_HPP
+#ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP
+#define BOOST_CONTAINER_CONTAINER_FWD_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -26,7 +26,7 @@ namespace intrusive{
    //Create namespace to avoid compilation errors
 }}
 
-namespace boost{ namespace container{ namespace containers_detail{
+namespace boost{ namespace container{ namespace container_detail{
 
 namespace bi = boost::intrusive;
 
@@ -195,4 +195,4 @@ struct dummy
 
 }}  //namespace boost { namespace container {
 
-#endif //#ifndef BOOST_CONTAINERS_CONTAINERS_FWD_HPP
+#endif //#ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP
diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp
index b890057..d77398b 100644
--- a/include/boost/container/deque.hpp
+++ b/include/boost/container/deque.hpp
@@ -30,8 +30,8 @@
 // representations about the suitability of this software for any
 // purpose.  It is provided "as is" without express or implied warranty.
 
-#ifndef BOOST_CONTAINERS_DEQUE_HPP
-#define BOOST_CONTAINERS_DEQUE_HPP
+#ifndef BOOST_CONTAINER_DEQUE_HPP
+#define BOOST_CONTAINER_DEQUE_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -44,6 +44,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -83,8 +84,8 @@ struct deque_value_traits
    static const bool trivial_copy = has_trivial_copy::value;
    static const bool nothrow_copy = has_nothrow_copy::value;
    static const bool trivial_assign = has_trivial_assign::value;
-   static const bool nothrow_assign = has_nothrow_assign::value;
-
+   //static const bool nothrow_assign = has_nothrow_assign::value;
+   static const bool nothrow_assign = false;
 };
 
 // Note: this function is simply a kludge to work around several compilers'
@@ -98,31 +99,32 @@ inline std::size_t deque_buf_size(std::size_t size)
 template 
 class deque_base
 {
+   BOOST_COPYABLE_AND_MOVABLE(deque_base)
    public:
-   typedef typename     A::value_type              val_alloc_val;
-   typedef typename     A::pointer                 val_alloc_ptr;
-   typedef typename     A::const_pointer           val_alloc_cptr;
-   typedef typename     A::reference               val_alloc_ref;
-   typedef typename     A::const_reference         val_alloc_cref;
-   typedef typename     A::difference_type         val_alloc_diff;
-   typedef typename     A::size_type               val_alloc_size;
-   typedef typename     A::template rebind
-      ::other             ptr_alloc_t;
-   typedef typename ptr_alloc_t::value_type        ptr_alloc_val;
-   typedef typename ptr_alloc_t::pointer           ptr_alloc_ptr;
-   typedef typename ptr_alloc_t::const_pointer     ptr_alloc_cptr;
-   typedef typename ptr_alloc_t::reference         ptr_alloc_ref;
-   typedef typename ptr_alloc_t::const_reference   ptr_alloc_cref;
-   typedef typename     A::template
-      rebind::other                             allocator_type;
-   typedef allocator_type                          stored_allocator_type;
-   typedef val_alloc_size                          size_type;
+   typedef allocator_traits                                     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::type                   ptr_alloc_t;
+   typedef allocator_traits                           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;
 
    protected:
 
-   typedef deque_value_traits            traits_t;
-   typedef typename     A::template
-      rebind::other map_allocator_type;
+   typedef deque_value_traits             traits_t;
+   typedef ptr_alloc_t                          map_allocator_type;
 
    static size_type s_buffer_size() { return deque_buf_size(sizeof(T)); }
 
@@ -373,7 +375,7 @@ class deque_base
          {  return static_cast(*this) - right;   }
    };
 
-   deque_base(const allocator_type& a, size_type num_elements)
+   deque_base(size_type num_elements, const allocator_type& a)
       :  members_(a)
    { this->priv_initialize_map(num_elements); }
 
@@ -381,6 +383,15 @@ class deque_base
       :  members_(a)
    {}
 
+   deque_base()
+      :  members_()
+   {}
+
+   explicit deque_base(BOOST_RV_REF(deque_base) x)
+      :  members_( boost::move(x.ptr_alloc())
+                 , boost::move(x.alloc()) )
+   {}
+
    ~deque_base()
    {
       if (this->members_.m_map) {
@@ -394,12 +405,20 @@ class deque_base
   
    protected:
 
+   void swap_members(deque_base &x)
+   {
+      std::swap(this->members_.m_start, x.members_.m_start);
+      std::swap(this->members_.m_finish, x.members_.m_finish);
+      std::swap(this->members_.m_map, x.members_.m_map);
+      std::swap(this->members_.m_map_size, x.members_.m_map_size);
+   }
+
    void priv_initialize_map(size_type num_elements)
    {
 //      if(num_elements){
          size_type num_nodes = num_elements / s_buffer_size() + 1;
 
-         this->members_.m_map_size = containers_detail::max_value((size_type) InitialMapSize, num_nodes + 2);
+         this->members_.m_map_size = container_detail::max_value((size_type) InitialMapSize, num_nodes + 2);
          this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size);
 
          ptr_alloc_ptr nstart = this->members_.m_map + (this->members_.m_map_size - num_nodes) / 2;
@@ -463,14 +482,28 @@ class deque_base
       :  public ptr_alloc_t
       ,  public allocator_type
    {
-      members_holder(const allocator_type &a)
+      members_holder()
+         :  map_allocator_type(), allocator_type()
+         ,  m_map(0), m_map_size(0)
+         ,  m_start(), m_finish(m_start)
+      {}
+
+      explicit members_holder(const allocator_type &a)
          :  map_allocator_type(a), allocator_type(a)
          ,  m_map(0), m_map_size(0)
          ,  m_start(), m_finish(m_start)
       {}
 
+      template
+      members_holder(BOOST_FWD_REF(PtrAllocConvertible) pa, BOOST_FWD_REF(ValAllocConvertible) va)
+         : map_allocator_type(boost::forward(pa))
+         , allocator_type    (boost::forward(va))
+         , m_map(0), m_map_size(0)
+         , m_start(), m_finish(m_start)
+      {}
+
       ptr_alloc_ptr   m_map;
-     typename allocator_type::size_type  m_map_size;
+      val_alloc_size  m_map_size;
       iterator        m_start;
       iterator        m_finish;
    } members_;
@@ -499,26 +532,25 @@ template 
 class deque : protected deque_base
 {
    /// @cond
-  typedef deque_base Base;
+   private:
+   typedef deque_base 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;
 
-   public:                         // Basic types
-   typedef typename     A::value_type           val_alloc_val;
-   typedef typename     A::pointer              val_alloc_ptr;
-   typedef typename     A::const_pointer        val_alloc_cptr;
-   typedef typename     A::reference            val_alloc_ref;
-   typedef typename     A::const_reference      val_alloc_cref;
-   typedef typename     A::size_type            val_alloc_size;
-   typedef typename     A::difference_type      val_alloc_diff;
-
-   typedef typename     A::template
-      rebind::other                ptr_alloc_t;
-   typedef typename ptr_alloc_t::value_type       ptr_alloc_val;
-   typedef typename ptr_alloc_t::pointer          ptr_alloc_ptr;
-   typedef typename ptr_alloc_t::const_pointer    ptr_alloc_cptr;
-   typedef typename ptr_alloc_t::reference        ptr_alloc_ref;
-   typedef typename ptr_alloc_t::const_reference  ptr_alloc_cref;
+   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;
@@ -535,6 +567,8 @@ class deque : protected deque_base
    typedef std::reverse_iterator const_reverse_iterator;
    typedef std::reverse_iterator      reverse_iterator;
 
+   typedef allocator_type                       stored_allocator_type;
+
    /// @cond
 
    private:                      // Internal typedefs
@@ -542,27 +576,49 @@ class deque : protected deque_base
    typedef ptr_alloc_ptr index_pointer;
    static size_type s_buffer_size() 
       { return Base::s_buffer_size(); }
-   typedef containers_detail::advanced_insert_aux_int advanced_insert_aux_int_t;
+   typedef container_detail::advanced_insert_aux_int advanced_insert_aux_int_t;
    typedef repeat_iterator  r_iterator;
-   typedef boost::move_iterator    move_it;
+   typedef boost::move_iterator     move_it;
+   typedef allocator_traits                  allocator_traits_type;
 
    /// @endcond
 
+   public:
+
    //! Effects: Returns a copy of the internal allocator.
    //! 
    //! Throws: If allocator's copy constructor throws.
    //! 
    //! Complexity: Constant.
-   allocator_type get_allocator() const { return Base::alloc(); }
+   allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
+   { return Base::alloc(); }
 
-   public:                         // Basic accessors
+   //! Effects: Returns a reference to the internal allocator.
+   //! 
+   //! Throws: Nothing
+   //! 
+   //! Complexity: Constant.
+   //! 
+   //! Note: Non-standard extension.
+   const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
+   {  return Base::alloc(); }
+
+   //! Effects: Returns a reference to the internal allocator.
+   //! 
+   //! Throws: Nothing
+   //! 
+   //! Complexity: Constant.
+   //! 
+   //! Note: Non-standard extension.
+   stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
+   {  return Base::alloc(); }
 
    //! Effects: Returns an iterator to the first element contained in the deque.
    //! 
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   iterator begin() 
+   iterator begin() BOOST_CONTAINER_NOEXCEPT
       { return this->members_.m_start; }
 
    //! Effects: Returns an iterator to the end of the deque.
@@ -570,7 +626,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   iterator end() 
+   iterator end() BOOST_CONTAINER_NOEXCEPT
       { return this->members_.m_finish; }
 
    //! Effects: Returns a const_iterator to the first element contained in the deque.
@@ -578,7 +634,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_iterator begin() const 
+   const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
       { return this->members_.m_start; }
 
    //! Effects: Returns a const_iterator to the end of the deque.
@@ -586,7 +642,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_iterator end() const 
+   const_iterator end() const BOOST_CONTAINER_NOEXCEPT
       { return this->members_.m_finish; }
 
    //! Effects: Returns a reverse_iterator pointing to the beginning 
@@ -595,7 +651,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   reverse_iterator rbegin() 
+   reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
       { return reverse_iterator(this->members_.m_finish); }
 
    //! Effects: Returns a reverse_iterator pointing to the end
@@ -604,7 +660,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   reverse_iterator rend() 
+   reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
       { return reverse_iterator(this->members_.m_start); }
 
    //! Effects: Returns a const_reverse_iterator pointing to the beginning 
@@ -613,7 +669,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reverse_iterator rbegin() const 
+   const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
       { return const_reverse_iterator(this->members_.m_finish); }
 
    //! Effects: Returns a const_reverse_iterator pointing to the end
@@ -622,7 +678,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reverse_iterator rend() const 
+   const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
       { return const_reverse_iterator(this->members_.m_start); }
 
    //! Effects: Returns a const_iterator to the first element contained in the deque.
@@ -630,7 +686,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_iterator cbegin() const 
+   const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
       { return this->members_.m_start; }
 
    //! Effects: Returns a const_iterator to the end of the deque.
@@ -638,7 +694,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_iterator cend() const 
+   const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
       { return this->members_.m_finish; }
 
    //! Effects: Returns a const_reverse_iterator pointing to the beginning 
@@ -647,7 +703,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reverse_iterator crbegin() const 
+   const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
       { return const_reverse_iterator(this->members_.m_finish); }
 
    //! Effects: Returns a const_reverse_iterator pointing to the end
@@ -656,7 +712,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reverse_iterator crend() const 
+   const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
       { return const_reverse_iterator(this->members_.m_start); }
 
    //! Requires: size() < n.
@@ -667,7 +723,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   reference operator[](size_type n)
+   reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
       { return this->members_.m_start[difference_type(n)]; }
 
    //! Requires: size() < n.
@@ -678,7 +734,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reference operator[](size_type n) const 
+   const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
       { return this->members_.m_start[difference_type(n)]; }
 
    //! Requires: size() < n.
@@ -711,7 +767,8 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   reference front() { return *this->members_.m_start; }
+   reference front() BOOST_CONTAINER_NOEXCEPT
+      { return *this->members_.m_start; }
 
    //! Requires: !empty()
    //!
@@ -721,7 +778,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reference front() const 
+   const_reference front() const BOOST_CONTAINER_NOEXCEPT
       { return *this->members_.m_start; }
 
    //! Requires: !empty()
@@ -732,7 +789,8 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   reference back()  {  return *(end()-1); }
+   reference back() BOOST_CONTAINER_NOEXCEPT
+      {  return *(end()-1); }
 
    //! Requires: !empty()
    //!
@@ -742,14 +800,15 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reference back() const  {  return *(cend()-1);  }
+   const_reference back() const BOOST_CONTAINER_NOEXCEPT
+      {  return *(cend()-1);  }
 
    //! Effects: Returns the number of the elements contained in the deque.
    //! 
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   size_type size() const 
+   size_type size() const BOOST_CONTAINER_NOEXCEPT
       { return this->members_.m_finish - this->members_.m_start; }
 
    //! Effects: Returns the largest possible size of the deque.
@@ -757,23 +816,32 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   size_type max_size() const 
-      { return this->alloc().max_size(); }
+   size_type max_size() const BOOST_CONTAINER_NOEXCEPT
+      { return allocator_traits_type::max_size(this->alloc()); }
 
    //! Effects: Returns true if the deque contains no elements.
    //! 
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   bool empty() const 
+   bool empty() const BOOST_CONTAINER_NOEXCEPT
    { return this->members_.m_finish == this->members_.m_start; }
 
+   //! Effects: Default constructors a deque.
+   //! 
+   //! Throws: If allocator_type's default constructor throws.
+   //! 
+   //! Complexity: Constant.
+   deque() 
+      : Base()
+   {}
+
    //! Effects: Constructs a deque taking the allocator as parameter.
    //! 
    //! Throws: If allocator_type's copy constructor throws.
    //! 
    //! Complexity: Constant.
-   explicit deque(const allocator_type& a = allocator_type()) 
+   explicit deque(const allocator_type& a) 
       : Base(a)
    {}
 
@@ -784,10 +852,11 @@ class deque : protected deque_base
    //!   throws or T's default or copy constructor throws.
    //! 
    //! Complexity: Linear to n.
-   explicit deque(size_type n) : Base(allocator_type(), n)
+   explicit deque(size_type n)
+      : Base(n, allocator_type())
    {
-      containers_detail::default_construct_aux_proxy proxy(n);
-      proxy.uninitialized_copy_all_to(this->begin());
+      container_detail::default_construct_aux_proxy proxy(this->alloc(), n);
+      proxy.uninitialized_copy_remaining_to(this->begin());
       //deque_base will deallocate in case of exception...
    }
 
@@ -799,7 +868,8 @@ class deque : protected deque_base
    //! 
    //! Complexity: Linear to n.
    deque(size_type n, const value_type& value,
-         const allocator_type& a = allocator_type()) : Base(a, n)
+         const allocator_type& a = allocator_type())
+      : Base(n, a)
    { this->priv_fill_initialize(value); }
 
    //! Effects: Copy constructs a deque.
@@ -808,11 +878,12 @@ class deque : protected deque_base
    //! 
    //! Complexity: Linear to the elements x contains.
    deque(const deque& x)
-      :  Base(x.alloc()) 
+      :  Base(allocator_traits_type::select_on_container_copy_construction(x.alloc()))
    {
       if(x.size()){
          this->priv_initialize_map(x.size());
-         std::uninitialized_copy(x.begin(), x.end(), this->members_.m_start);
+         boost::container::uninitialized_copy_alloc
+            (this->alloc(), x.begin(), x.end(), this->members_.m_start);
       }
    }
 
@@ -821,9 +892,9 @@ class deque : protected deque_base
    //! Throws: If allocator_type's copy constructor throws.
    //! 
    //! Complexity: Constant.
-   deque(BOOST_RV_REF(deque) mx) 
-      :  Base(mx.alloc())
-   {  this->swap(mx);   }
+   deque(BOOST_RV_REF(deque) x) 
+      :  Base(boost::move(static_cast(x)))
+   {  this->swap_members(x);   }
 
    //! Effects: Constructs a deque that will use a copy of allocator a
    //!   and inserts a copy of the range [first, last) in the deque.
@@ -837,8 +908,8 @@ class deque : protected deque_base
       : Base(a) 
    {
       //Dispatch depending on integer/iterator
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_initialize_dispatch(first, last, Result());
    }
 
@@ -848,7 +919,7 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //!
    //! Complexity: Linear to the number of elements.
-   ~deque() 
+   ~deque() BOOST_CONTAINER_NOEXCEPT
    {
       priv_destroy_range(this->members_.m_start, this->members_.m_finish);
    }
@@ -863,15 +934,18 @@ class deque : protected deque_base
    //! Complexity: Linear to the number of elements in x.
    deque& operator= (BOOST_COPY_ASSIGN_REF(deque) x) 
    {
-      const size_type len = size();
-      if (&x != this) {
-         if (len >= x.size())
-            this->erase(std::copy(x.begin(), x.end(), this->members_.m_start), this->members_.m_finish);
-         else {
-            const_iterator mid = x.begin() + difference_type(len);
-            std::copy(x.begin(), mid, this->members_.m_start);
-            this->insert(this->members_.m_finish, mid, x.end());
+      if (&x != this){
+         allocator_type &this_alloc     = this->alloc();
+         const allocator_type &x_alloc  = x.alloc();
+         container_detail::bool_ flag;
+         if(flag && this_alloc != x_alloc){
+            this->clear();
+            this->shrink_to_fit();
          }
+         container_detail::assign_alloc(this->alloc(), x.alloc(), flag);
+         container_detail::assign_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
+         this->assign(x.cbegin(), x.cend());
       }
       return *this;
    }
@@ -886,8 +960,27 @@ class deque : protected deque_base
    //! Complexity: Linear.
    deque& operator= (BOOST_RV_REF(deque) x)
    {
-      this->clear();
-      this->swap(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_ 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_category ItCat;
+            this->assign( boost::make_move_iterator(x.begin())
+                        , boost::make_move_iterator(x.end()));
+         }
+      }
       return *this;
    }
 
@@ -900,10 +993,10 @@ class deque : protected deque_base
    //! Complexity: Constant.
    void swap(deque &x)
    {
-      std::swap(this->members_.m_start, x.members_.m_start);
-      std::swap(this->members_.m_finish, x.members_.m_finish);
-      std::swap(this->members_.m_map, x.members_.m_map);
-      std::swap(this->members_.m_map_size, x.members_.m_map_size);
+      this->swap_members(x);
+      container_detail::bool_ flag;
+      container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
+      container_detail::swap_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
    }
 
    //! Effects: Assigns the n copies of val to *this.
@@ -924,8 +1017,8 @@ class deque : protected deque_base
    void assign(InpIt first, InpIt last)
    {
       //Dispatch depending on integer/iterator
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_assign_dispatch(first, last, Result());
    }
 
@@ -974,11 +1067,11 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //!
    //! Complexity: Constant time.
-   void pop_back() 
+   void pop_back() BOOST_CONTAINER_NOEXCEPT
    {
       if (this->members_.m_finish.m_cur != this->members_.m_finish.m_first) {
          --this->members_.m_finish.m_cur;
-         containers_detail::get_pointer(this->members_.m_finish.m_cur)->~value_type();
+         container_detail::to_raw_pointer(this->members_.m_finish.m_cur)->~value_type();
       }
       else
          this->priv_pop_back_aux();
@@ -989,10 +1082,10 @@ class deque : protected deque_base
    //! Throws: Nothing.
    //!
    //! Complexity: Constant time.
-   void pop_front() 
+   void pop_front() BOOST_CONTAINER_NOEXCEPT
    {
       if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) {
-         containers_detail::get_pointer(this->members_.m_start.m_cur)->~value_type();
+         container_detail::to_raw_pointer(this->members_.m_start.m_cur)->~value_type();
          ++this->members_.m_start.m_cur;
       }
       else 
@@ -1046,12 +1139,12 @@ class deque : protected deque_base
    void insert(const_iterator pos, InpIt first, InpIt last) 
    {
       //Dispatch depending on integer/iterator
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_insert_dispatch(pos, first, last, Result());
    }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... in the end of the deque.
@@ -1063,13 +1156,16 @@ class deque : protected deque_base
    void emplace_back(Args&&... args)
    {
       if(this->priv_push_back_simple_available()){
-         new(this->priv_push_back_simple_pos())value_type(boost::forward(args)...);
+         allocator_traits_type::construct
+            ( this->alloc()
+            , this->priv_push_back_simple_pos()
+            , boost::forward(args)...);
          this->priv_push_back_simple_commit();
       }
       else{
-         typedef containers_detail::advanced_insert_aux_emplace type;
-         type &&proxy = type(boost::forward(args)...);
-         this->priv_insert_aux_impl(this->cend(), 1, proxy);
+         typedef container_detail::advanced_insert_aux_non_movable_emplace type;
+         type &&proxy = type(this->alloc(), boost::forward(args)...);
+         this->priv_insert_back_aux_impl(1, proxy);
       }
    }
 
@@ -1083,13 +1179,16 @@ class deque : protected deque_base
    void emplace_front(Args&&... args)
    {
       if(this->priv_push_front_simple_available()){
-         new(this->priv_push_front_simple_pos())value_type(boost::forward(args)...);
+         allocator_traits_type::construct
+            ( this->alloc()
+            , this->priv_push_front_simple_pos()
+            , boost::forward(args)...);
          this->priv_push_front_simple_commit();
       }
       else{
-         typedef containers_detail::advanced_insert_aux_emplace type;
-         type &&proxy = type(boost::forward(args)...);
-         this->priv_insert_aux_impl(this->cbegin(), 1, proxy);
+         typedef container_detail::advanced_insert_aux_non_movable_emplace type;
+         type &&proxy = type(this->alloc(), boost::forward(args)...);
+         this->priv_insert_front_aux_impl(1, proxy);
       }
    }
 
@@ -1115,117 +1214,81 @@ class deque : protected deque_base
       }
       else{
          size_type n = p - this->cbegin();
-         typedef containers_detail::advanced_insert_aux_emplace type;
-         type &&proxy = type(boost::forward(args)...);
+         typedef container_detail::advanced_insert_aux_emplace type;
+         type &&proxy = type(this->alloc(), boost::forward(args)...);
          this->priv_insert_aux_impl(p, 1, proxy);
          return iterator(this->begin() + n);
       }
    }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
-
-   //0 args
-   void emplace_back()
-   {
-      if(priv_push_front_simple_available()){
-         new(priv_push_front_simple_pos())value_type();
-         priv_push_front_simple_commit();
-      }
-      else{
-         containers_detail::advanced_insert_aux_emplace proxy;
-         priv_insert_aux_impl(cend(), 1, proxy);
-      }
-   }
-
-   void emplace_front()
-   {
-      if(priv_push_front_simple_available()){
-         new(priv_push_front_simple_pos())value_type();
-         priv_push_front_simple_commit();
-      }
-      else{
-         containers_detail::advanced_insert_aux_emplace proxy;
-         priv_insert_aux_impl(cbegin(), 1, proxy);
-      }
-   }
-
-   iterator emplace(const_iterator p)
-   {
-      if(p == cbegin()){
-         emplace_front();
-         return begin();
-      }
-      else if(p == cend()){
-         emplace_back();
-         return (end()-1);
-      }
-      else{
-         size_type n = p - cbegin();
-         containers_detail::advanced_insert_aux_emplace proxy;
-         priv_insert_aux_impl(p, 1, proxy);
-         return iterator(this->begin() + n);
-      }
-   }
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //advanced_insert_int.hpp includes all necessary preprocessor machinery...
    #define BOOST_PP_LOCAL_MACRO(n)                                                           \
-   template                                                \
-   void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_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_back_simple_available()){                                                 \
-         new(priv_push_back_simple_pos())value_type                                          \
-         (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                         \
+         allocator_traits_type::construct                                                    \
+            ( this->alloc()                                                                  \
+            , this->priv_push_back_simple_pos()                                              \
+              BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));               \
          priv_push_back_simple_commit();                                                     \
       }                                                                                      \
       else{                                                                                  \
-         containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)             \
-                                           \
-               proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));              \
-         priv_insert_aux_impl(cend(), 1, proxy);                                             \
+         container_detail::BOOST_PP_CAT(BOOST_PP_CAT(                                        \
+            advanced_insert_aux_non_movable_emplace, n), arg)                                \
+                proxy                       \
+            (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));  \
+         priv_insert_back_aux_impl(1, proxy);                                                \
       }                                                                                      \
    }                                                                                         \
                                                                                              \
-   template                                                \
-   void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINERS_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_front_simple_available()){                                                \
-         new(priv_push_front_simple_pos())value_type                                         \
-            (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                      \
+         allocator_traits_type::construct                                                    \
+            ( this->alloc()                                                                  \
+            , this->priv_push_front_simple_pos()                                             \
+              BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));               \
          priv_push_front_simple_commit();                                                    \
       }                                                                                      \
       else{                                                                                  \
-         containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)             \
-                                           \
-               proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));              \
-         priv_insert_aux_impl(cbegin(), 1, proxy);                                           \
+         container_detail::BOOST_PP_CAT(BOOST_PP_CAT                                         \
+            (advanced_insert_aux_non_movable_emplace, n), arg)                               \
+                proxy                       \
+            (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));  \
+         priv_insert_front_aux_impl(1, proxy);                                               \
       }                                                                                      \
    }                                                                                         \
                                                                                              \
-   template                                                \
-   iterator emplace(const_iterator p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
+   BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >)    \
+   iterator emplace(const_iterator p                                                         \
+                    BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _))             \
    {                                                                                         \
       if(p == this->cbegin()){                                                               \
-         this->emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));      \
+         this->emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));         \
          return this->begin();                                                               \
       }                                                                                      \
       else if(p == cend()){                                                                  \
-         this->emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));       \
+         this->emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));          \
          return (this->end()-1);                                                             \
       }                                                                                      \
       else{                                                                                  \
          size_type pos_num = p - this->cbegin();                                             \
-         containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)             \
-                                           \
-               proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));              \
+         container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)   \
+             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);                                           \
       }                                                                                      \
    }                                                                                         \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Inserts or erases elements at the end such that
    //!   the size becomes n. New elements are copy constructed from x.
@@ -1252,11 +1315,11 @@ class deque : protected deque_base
    {
       const size_type len = size();
       if (new_size < len) 
-         this->erase(this->members_.m_start + new_size, this->members_.m_finish);
+         this->priv_erase_last_n(len - new_size);
       else{
          size_type n = new_size - this->size();
-         containers_detail::default_construct_aux_proxy proxy(n);
-         priv_insert_aux_impl(this->cend(), n, proxy);
+         container_detail::default_construct_aux_proxy proxy(this->alloc(), n);
+         priv_insert_back_aux_impl(n, proxy);
       }
    }
 
@@ -1268,7 +1331,7 @@ class deque : protected deque_base
    //!   last element (if pos is near the end) or the first element
    //!   if(pos is near the beginning).
    //!   Constant if pos is the first or the last element.
-   iterator erase(const_iterator pos) 
+   iterator erase(const_iterator pos) BOOST_CONTAINER_NOEXCEPT
    {
       const_iterator next = pos;
       ++next;
@@ -1292,7 +1355,7 @@ class deque : protected deque_base
    //!   last plus the elements between pos and the 
    //!   last element (if pos is near the end) or the first element
    //!   if(pos is near the beginning).
-   iterator erase(const_iterator first, const_iterator last)
+   iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
    {
       if (first == this->members_.m_start && last == this->members_.m_finish) {
          this->clear();
@@ -1321,12 +1384,26 @@ class deque : protected deque_base
       }
    }
 
+   void priv_erase_last_n(size_type n)
+   {
+      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;
+      }
+   }
+
    //! Effects: Erases all the elements of the deque.
    //!
    //! Throws: Nothing.
    //!
    //! Complexity: Linear to the number of elements in the deque.
-   void clear()
+   void clear() BOOST_CONTAINER_NOEXCEPT
    {
       for (index_pointer node = this->members_.m_start.m_node + 1;
             node < this->members_.m_finish.m_node;
@@ -1365,7 +1442,6 @@ class deque : protected deque_base
 
    /// @cond
    private:
-
    void priv_range_check(size_type n) const 
       {  if (n >= this->size())  BOOST_RETHROW std::out_of_range("deque");   }
 
@@ -1407,7 +1483,8 @@ class deque : protected deque_base
    void priv_push_front(const value_type &t)
    {
       if(this->priv_push_front_simple_available()){
-         new(this->priv_push_front_simple_pos())value_type(t);
+         allocator_traits_type::construct
+            ( this->alloc(), this->priv_push_front_simple_pos(), t);
          this->priv_push_front_simple_commit();
       }
       else{
@@ -1418,7 +1495,8 @@ class deque : protected deque_base
    void priv_push_front(BOOST_RV_REF(value_type) t)
    {
       if(this->priv_push_front_simple_available()){
-         new(this->priv_push_front_simple_pos())value_type(boost::move(t));
+         allocator_traits_type::construct
+            ( this->alloc(), this->priv_push_front_simple_pos(), boost::move(t));
          this->priv_push_front_simple_commit();
       }
       else{
@@ -1429,7 +1507,8 @@ class deque : protected deque_base
    void priv_push_back(const value_type &t)
    {
       if(this->priv_push_back_simple_available()){
-         new(this->priv_push_back_simple_pos())value_type(t);
+         allocator_traits_type::construct
+            ( this->alloc(), this->priv_push_back_simple_pos(), t);
          this->priv_push_back_simple_commit();
       }
       else{
@@ -1440,7 +1519,8 @@ class deque : protected deque_base
    void priv_push_back(BOOST_RV_REF(T) t)
    {
       if(this->priv_push_back_simple_available()){
-         new(this->priv_push_back_simple_pos())value_type(boost::move(t));
+         allocator_traits_type::construct
+            ( this->alloc(), this->priv_push_back_simple_pos(), boost::move(t));
          this->priv_push_back_simple_commit();
       }
       else{
@@ -1454,9 +1534,9 @@ class deque : protected deque_base
          (this->members_.m_finish.m_cur != (this->members_.m_finish.m_last - 1));
    }
 
-   void *priv_push_back_simple_pos() const
+   T *priv_push_back_simple_pos() const
    {
-      return static_cast(containers_detail::get_pointer(this->members_.m_finish.m_cur));
+      return container_detail::to_raw_pointer(this->members_.m_finish.m_cur);
    }
 
    void priv_push_back_simple_commit()
@@ -1470,8 +1550,8 @@ class deque : protected deque_base
          (this->members_.m_start.m_cur != this->members_.m_start.m_first);
    }
 
-   void *priv_push_front_simple_pos() const
-   {  return static_cast(containers_detail::get_pointer(this->members_.m_start.m_cur) - 1);  }
+   T *priv_push_front_simple_pos() const
+   {  return container_detail::to_raw_pointer(this->members_.m_start.m_cur) - 1;  }
 
    void priv_push_front_simple_commit()
    {  --this->members_.m_start.m_cur;   }
@@ -1505,14 +1585,14 @@ class deque : protected deque_base
    }
 
    template 
-   void priv_initialize_dispatch(Integer n, Integer x, containers_detail::true_) 
+   void priv_initialize_dispatch(Integer n, Integer x, container_detail::true_) 
    {
       this->priv_initialize_map(n);
       this->priv_fill_initialize(x);
    }
 
    template 
-   void priv_initialize_dispatch(InpIt first, InpIt last, containers_detail::false_) 
+   void priv_initialize_dispatch(InpIt first, InpIt last, container_detail::false_) 
    {
       typedef typename std::iterator_traits::iterator_category ItCat;
       this->priv_range_initialize(first, last, ItCat());
@@ -1521,21 +1601,21 @@ class deque : protected deque_base
    void priv_destroy_range(iterator p, iterator p2)
    {
       for(;p != p2; ++p)
-         containers_detail::get_pointer(&*p)->~value_type();
+         container_detail::to_raw_pointer(&*p)->~value_type();
    }
 
    void priv_destroy_range(pointer p, pointer p2)
    {
       for(;p != p2; ++p)
-         containers_detail::get_pointer(&*p)->~value_type();
+         container_detail::to_raw_pointer(&*p)->~value_type();
    }
 
    template 
-   void priv_assign_dispatch(Integer n, Integer val, containers_detail::true_)
+   void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
       { this->priv_fill_assign((size_type) n, (value_type)val); }
 
    template 
-   void priv_assign_dispatch(InpIt first, InpIt last, containers_detail::false_) 
+   void priv_assign_dispatch(InpIt first, InpIt last, container_detail::false_) 
    {
       typedef typename std::iterator_traits::iterator_category ItCat;
       this->priv_assign_aux(first, last, ItCat());
@@ -1560,19 +1640,19 @@ class deque : protected deque_base
       if (len > size()) {
          FwdIt mid = first;
          std::advance(mid, size());
-         std::copy(first, mid, begin());
+         boost::copy_or_move(first, mid, begin());
          this->insert(cend(), mid, last);
       }
       else
-         this->erase(std::copy(first, last, begin()), cend());
+         this->erase(boost::copy_or_move(first, last, begin()), cend());
    }
 
    template 
-   void priv_insert_dispatch(const_iterator pos, Integer n, Integer x, containers_detail::true_) 
+   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 
-   void priv_insert_dispatch(const_iterator pos,InpIt first, InpIt last, containers_detail::false_) 
+   void priv_insert_dispatch(const_iterator pos,InpIt first, InpIt last, container_detail::false_) 
    {
       typedef typename std::iterator_traits::iterator_category ItCat;
       this->priv_insert_aux(pos, first, last, ItCat());
@@ -1588,7 +1668,7 @@ class deque : protected deque_base
    template 
    void priv_insert_aux(const_iterator p, FwdIt first, FwdIt last)
    {
-      containers_detail::advanced_insert_aux_proxy proxy(first, last);
+      container_detail::advanced_insert_aux_proxy proxy(this->alloc(), first, last);
       priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy);
    }
 
@@ -1608,19 +1688,21 @@ class deque : protected deque_base
          pos = this->members_.m_start + elemsbefore;
          if (elemsbefore >= difference_type(n)) {
             iterator start_n = this->members_.m_start + difference_type(n); 
-            ::boost::uninitialized_move(this->members_.m_start, start_n, new_start);
+            ::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);
-            interf.copy_all_to(pos - difference_type(n));
+            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::uninitialized_move(old_start, pos, new_start);
+            ::boost::container::uninitialized_move_alloc
+               (this->alloc(), old_start, pos, new_start);
             this->members_.m_start = new_start;
-            interf.copy_all_to(old_start);
+            interf.copy_remaining_to(old_start);
          }
       }
       else {
@@ -1631,21 +1713,47 @@ class deque : protected deque_base
          pos = this->members_.m_finish - elemsafter;
          if (elemsafter >= difference_type(n)) {
             iterator finish_n = this->members_.m_finish - difference_type(n);
-            ::boost::uninitialized_move(finish_n, this->members_.m_finish, this->members_.m_finish);
+            ::boost::container::uninitialized_move_alloc
+               (this->alloc(), finish_n, this->members_.m_finish, this->members_.m_finish);
             this->members_.m_finish = new_finish;
             boost::move_backward(pos, finish_n, old_finish);
-            interf.copy_all_to(pos);
+            interf.copy_remaining_to(pos);
          }
          else {
             interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
             this->members_.m_finish += n-elemsafter;
-            ::boost::uninitialized_move(pos, old_finish, this->members_.m_finish);
+            ::boost::container::uninitialized_move_alloc
+               (this->alloc(), pos, old_finish, this->members_.m_finish);
             this->members_.m_finish = new_finish;
-            interf.copy_all_to(pos);
+            interf.copy_remaining_to(pos);
          }
       }
    }
 
+   void priv_insert_back_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
+   {
+      if(!this->members_.m_map){
+         this->priv_initialize_map(0);
+      }
+
+      iterator new_finish = this->priv_reserve_elements_at_back(n);
+      iterator old_finish = this->members_.m_finish;
+      interf.uninitialized_copy_some_and_update(old_finish, n, true);
+      this->members_.m_finish = new_finish;
+   }
+
+   void priv_insert_front_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
+   {
+      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);
+      this->members_.m_start = new_start;
+   }
+
+
    void priv_fill_insert(const_iterator pos, size_type n, const value_type& x)
    {
       typedef constant_iterator c_it;
@@ -1659,9 +1767,11 @@ class deque : protected deque_base
       index_pointer cur;
       BOOST_TRY {
          for (cur = this->members_.m_start.m_node; cur < this->members_.m_finish.m_node; ++cur){
-            std::uninitialized_fill(*cur, *cur + this->s_buffer_size(), value);
+            boost::container::uninitialized_fill_alloc
+               (this->alloc(), *cur, *cur + this->s_buffer_size(), value);
          }
-         std::uninitialized_fill(this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value);
+         boost::container::uninitialized_fill_alloc
+            (this->alloc(), this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value);
       }
       BOOST_CATCH(...){
          this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur));
@@ -1699,10 +1809,12 @@ class deque : protected deque_base
                ++cur_node) {
             FwdIt mid = first;
             std::advance(mid, this->s_buffer_size());
-            ::boost::uninitialized_copy_or_move(first, mid, *cur_node);
+            ::boost::container::uninitialized_copy_or_move_alloc
+               (this->alloc(), first, mid, *cur_node);
             first = mid;
          }
-         ::boost::uninitialized_copy_or_move(first, last, this->members_.m_finish.m_first);
+         ::boost::container::uninitialized_copy_or_move_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));
@@ -1717,7 +1829,7 @@ class deque : protected deque_base
       this->priv_deallocate_node(this->members_.m_finish.m_first);
       this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1);
       this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1;
-      containers_detail::get_pointer(this->members_.m_finish.m_cur)->~value_type();
+      container_detail::to_raw_pointer(this->members_.m_finish.m_cur)->~value_type();
    }
 
    // Called only if this->members_.m_start.m_cur == this->members_.m_start.m_last - 1.  Note that 
@@ -1726,7 +1838,7 @@ class deque : protected deque_base
    // must have at least two nodes.
    void priv_pop_front_aux()
    {
-      containers_detail::get_pointer(this->members_.m_start.m_cur)->~value_type();
+      container_detail::to_raw_pointer(this->members_.m_start.m_cur)->~value_type();
       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;
@@ -1800,7 +1912,7 @@ class deque : protected deque_base
       }
       else {
          size_type new_map_size = 
-            this->members_.m_map_size + containers_detail::max_value(this->members_.m_map_size, nodes_to_add) + 2;
+            this->members_.m_map_size + container_detail::max_value(this->members_.m_map_size, nodes_to_add) + 2;
 
          index_pointer new_map = this->priv_allocate_map(new_map_size);
          new_nstart = new_map + (new_map_size - new_num_nodes) / 2
@@ -1878,4 +1990,4 @@ struct has_trivial_destructor_after_move >
 
 #include 
 
-#endif //   #ifndef  BOOST_CONTAINERS_DEQUE_HPP
+#endif //   #ifndef  BOOST_CONTAINER_DEQUE_HPP
diff --git a/include/boost/container/detail/adaptive_node_pool_impl.hpp b/include/boost/container/detail/adaptive_node_pool_impl.hpp
index d462ee3..3649579 100644
--- a/include/boost/container/detail/adaptive_node_pool_impl.hpp
+++ b/include/boost/container/detail/adaptive_node_pool_impl.hpp
@@ -19,7 +19,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -31,7 +31,7 @@
 
 namespace boost {
 namespace container {
-namespace containers_detail {
+namespace container_detail {
 
 template
 struct hdr_offset_holder_t
@@ -221,7 +221,7 @@ class private_adaptive_node_pool_impl
 
    //!Returns the segment manager. Never throws
    segment_manager_base_type* get_segment_manager_base()const
-   {  return containers_detail::get_pointer(mp_segment_mngr_base);  }
+   {  return container_detail::to_raw_pointer(mp_segment_mngr_base);  }
 
    //!Allocates array of count elements. Can throw
    void *allocate_node()
@@ -348,7 +348,7 @@ class private_adaptive_node_pool_impl
    {
       block_iterator block_it(m_block_multiset.end());
       while(n--){
-         void *pElem = containers_detail::get_pointer(chain.front());
+         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);
@@ -434,7 +434,7 @@ class private_adaptive_node_pool_impl
          (void)free_nodes;
          BOOST_ASSERT(free_nodes == 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(containers_detail::get_pointer(to_deallocate));
+         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);
       }
 
@@ -557,7 +557,7 @@ class private_adaptive_node_pool_impl
             (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;
+         block_info_t *c_info = new(mem_address)block_info_t();
          m_block_multiset.insert(m_block_multiset.end(), *c_info);
          
          mem_address += HdrSize;
@@ -587,7 +587,7 @@ class private_adaptive_node_pool_impl
 
          //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(&static_cast(c_info)->hdr_offset) ==
                 static_cast(c_info));
@@ -622,8 +622,8 @@ class private_adaptive_node_pool_impl
    {  return priv_alloc_block(n, IsAlignOnly());   }
 
    private:
-   typedef typename boost::pointer_to_other
-      ::type   segment_mngr_base_ptr_t;
+   typedef typename boost::intrusive::pointer_traits
+      ::template rebind_pointer::type   segment_mngr_base_ptr_t;
    const size_type m_max_free_blocks;
    const size_type m_real_node_size;
    //Round the size to a power of two value.
@@ -639,7 +639,7 @@ class private_adaptive_node_pool_impl
    size_type                            m_totally_free_blocks;  //Free blocks
 };
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 }  //namespace container {
 }  //namespace boost {
 
diff --git a/include/boost/container/detail/advanced_insert_int.hpp b/include/boost/container/detail/advanced_insert_int.hpp
index 77f3547..58199c7 100644
--- a/include/boost/container/detail/advanced_insert_int.hpp
+++ b/include/boost/container/detail/advanced_insert_int.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
-#define BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
+#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
+#define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -17,54 +17,58 @@
 
 #include "config_begin.hpp"
 #include 
+#include 
 #include 
 #include   //std::iterator_traits
-#include        //placement new
 #include 
 
-namespace boost { namespace container { namespace containers_detail {
+namespace boost { namespace container { namespace container_detail {
 
 //This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl
-template
+template
 struct advanced_insert_aux_int
 {
    typedef typename std::iterator_traits::difference_type difference_type;
-   virtual void copy_all_to(Iterator p) = 0;
-   virtual void uninitialized_copy_all_to(Iterator p) = 0;
+   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() {}
 };
 
 //This class template will adapt each FwIt types to advanced_insert_aux_int
-template
+template
 struct advanced_insert_aux_proxy
-   :  public advanced_insert_aux_int
+   :  public advanced_insert_aux_int
 {
-   typedef typename advanced_insert_aux_int::difference_type difference_type;
-   advanced_insert_aux_proxy(FwdIt first, FwdIt last)
-      :  first_(first), last_(last)
+   typedef boost::container::allocator_traits alloc_traits;
+   typedef typename allocator_traits::size_type size_type;
+   typedef typename allocator_traits::value_type value_type;
+   typedef typename advanced_insert_aux_int::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()
    {}
 
-   virtual void copy_all_to(Iterator p)
+   virtual void copy_remaining_to(Iterator p)
    {  ::boost::copy_or_move(first_, last_, p);  }
 
-   virtual void uninitialized_copy_all_to(Iterator p)
-   {  ::boost::uninitialized_copy_or_move(first_, last_, p);  }
+   virtual void uninitialized_copy_remaining_to(Iterator p)
+   {  ::boost::container::uninitialized_copy_or_move_alloc(a_, first_, last_, p);  }
 
    virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
    {
       FwdIt mid = first_;
       std::advance(mid, division_count);
       if(first_n){
-         ::boost::uninitialized_copy_or_move(first_, mid, pos);
+         ::boost::container::uninitialized_copy_or_move_alloc(a_, first_, mid, pos);
          first_ = mid;
       }
       else{
-         ::boost::uninitialized_copy_or_move(mid, last_, pos);
+         ::boost::container::uninitialized_copy_or_move_alloc(a_, mid, last_, pos);
          last_ = mid;
       }
    }
@@ -82,53 +86,38 @@ struct advanced_insert_aux_proxy
          last_ = mid;
       }
    }
-
+   A &a_;
    FwdIt first_, last_;
 };
 
-//This class template will adapt each FwIt types to advanced_insert_aux_int
-template
+//This class template will adapt default construction insertions to advanced_insert_aux_int
+template
 struct default_construct_aux_proxy
-   :  public advanced_insert_aux_int
+   :  public advanced_insert_aux_int
 {
-   typedef typename advanced_insert_aux_int::difference_type difference_type;
-   default_construct_aux_proxy(SizeType count)
-      :  count_(count)
-   {}
+   typedef boost::container::allocator_traits alloc_traits;
+   typedef typename allocator_traits::size_type size_type;
+   typedef typename allocator_traits::value_type value_type;
+   typedef typename advanced_insert_aux_int::difference_type difference_type;
 
-   void uninitialized_copy_impl(Iterator p, const SizeType n)
-   {
-      BOOST_ASSERT(n <= count_);
-      Iterator orig_p = p;
-      SizeType i = 0;
-      try{
-         for(; i < n; ++i, ++p){
-            new(containers_detail::get_pointer(&*p))T();
-         }
-      }
-      catch(...){
-         while(i--){
-            containers_detail::get_pointer(&*orig_p++)->~T();
-         }
-         throw;
-      }
-      count_ -= n;
-   }
+   default_construct_aux_proxy(A &a, size_type count)
+      :  a_(a), count_(count)
+   {}
 
    virtual ~default_construct_aux_proxy()
    {}
 
-   virtual void copy_all_to(Iterator)
+   virtual void copy_remaining_to(Iterator)
    {  //This should never be called with any count
       BOOST_ASSERT(count_ == 0);
    }
 
-   virtual void uninitialized_copy_all_to(Iterator p)
-   {  this->uninitialized_copy_impl(p, count_); }
+   virtual void uninitialized_copy_remaining_to(Iterator p)
+   {  this->priv_uninitialized_copy(p, count_); }
 
    virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
    {
-      SizeType new_count;
+      size_type new_count;
       if(first_n){
          new_count = division_count;
       }
@@ -136,13 +125,13 @@ struct default_construct_aux_proxy
          BOOST_ASSERT(difference_type(count_)>= division_count);
          new_count = count_ - division_count;
       }
-      this->uninitialized_copy_impl(pos, new_count);
+      this->priv_uninitialized_copy(pos, new_count);
    }
 
    virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n)
    {
       BOOST_ASSERT(count_ == 0);
-      SizeType new_count;
+      size_type new_count;
       if(first_n){
          new_count = division_count;
       }
@@ -155,12 +144,32 @@ struct default_construct_aux_proxy
       (void)new_count;
    }
 
-   SizeType count_;
+   private:
+   void priv_uninitialized_copy(Iterator p, const size_type n)
+   {
+      BOOST_ASSERT(n <= count_);
+      Iterator orig_p = p;
+      size_type i = 0;
+      try{
+         for(; i < n; ++i, ++p){
+            alloc_traits::construct(a_, container_detail::to_raw_pointer(&*p));
+         }
+      }
+      catch(...){
+         while(i--){
+            alloc_traits::destroy(a_, container_detail::to_raw_pointer(&*orig_p++));
+         }
+         throw;
+      }
+      count_ -= n;
+   }
+   A &a_;
+   size_type count_;
 };
 
-}}}   //namespace boost { namespace container { namespace containers_detail {
+}}}   //namespace boost { namespace container { namespace container_detail {
 
-#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
 #include 
 #include 
@@ -169,217 +178,251 @@ struct default_construct_aux_proxy
 //#include  //For debugging purposes
 
 namespace boost {
-namespace container { 
-namespace containers_detail {
+namespace container {
+namespace container_detail {
 
-//This class template will adapt each FwIt types to advanced_insert_aux_int
-template
-struct advanced_insert_aux_emplace
-   :  public advanced_insert_aux_int
+
+//This class template will adapt emplace construction insertions of movable types 
+//to advanced_insert_aux_int
+template
+struct advanced_insert_aux_non_movable_emplace
+   :  public advanced_insert_aux_int
 {
-   typedef typename advanced_insert_aux_int::difference_type difference_type;
+   typedef boost::container::allocator_traits alloc_traits;
+   typedef typename allocator_traits::size_type size_type;
+   typedef typename allocator_traits::value_type value_type;
+   typedef typename advanced_insert_aux_int::difference_type difference_type;
    typedef typename build_number_seq::type             index_tuple_t;
 
-   explicit advanced_insert_aux_emplace(Args&&... args)
-      : args_(args...)
+   explicit advanced_insert_aux_non_movable_emplace(A &a, Args&&... args)
+      : a_(a)
+      , args_(args...)
       , used_(false)
    {}
 
-   ~advanced_insert_aux_emplace()
+   ~advanced_insert_aux_non_movable_emplace()
    {}
 
-   virtual void copy_all_to(Iterator p)
-   {  this->priv_copy_all_to(index_tuple_t(), p);   }
+   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_all_to(Iterator p)
-   {  this->priv_uninitialized_copy_all_to(index_tuple_t(), p);   }
+   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 p, difference_type division_count, bool first_n)
-   {  this->priv_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);   }
 
    private:
-   template
-   void priv_copy_all_to(const index_tuple&, Iterator p)
-   {
-      if(!used_){
-         *p = boost::move(T (::boost::container::containers_detail::stored_ref::forward(get(args_))...));
-         used_ = true;
-      }
-   }
-
-   template
-   void priv_uninitialized_copy_all_to(const index_tuple&, Iterator p)
-   {
-      if(!used_){
-         new(containers_detail::get_pointer(&*p))T(::boost::container::containers_detail::stored_ref::forward(get(args_))...);
-         used_ = true;
-      }
-   }
-
    template
    void priv_uninitialized_copy_some_and_update(const index_tuple&, 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(!used_){
-            new(containers_detail::get_pointer(&*p))T(::boost::container::containers_detail::stored_ref::forward(get(args_))...);
+            alloc_traits::construct( a_
+                                   , container_detail::to_raw_pointer(&*p)
+                                   , ::boost::container::container_detail::
+                                       stored_ref::forward(get(args_))...
+                                   );
             used_ = true;
          }
       }
    }
 
+   template
+   void priv_uninitialized_copy_remaining_to(const index_tuple&, Iterator p)
+   {
+      if(!used_){
+         alloc_traits::construct( a_
+                                , container_detail::to_raw_pointer(&*p)
+                                , ::boost::container::container_detail::
+                                    stored_ref::forward(get(args_))...
+                                );
+         used_ = true;
+      }
+   }
+
+   protected:
+   A &a_;
+   tuple args_;
+   bool used_;
+};
+
+//This class template will adapt emplace construction insertions of movable types 
+//to advanced_insert_aux_int
+template
+struct advanced_insert_aux_emplace
+   :  public advanced_insert_aux_non_movable_emplace
+{
+   typedef advanced_insert_aux_non_movable_emplace base_t;
+   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)...)
+   {}
+
+   ~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);  }
+
+   private:
+   template
+   void priv_copy_remaining_to(const index_tuple&, Iterator p)
+   {
+      if(!this->used_){
+         *p = boost::move(value_type (
+            ::boost::container::container_detail::stored_ref::forward(get(this->args_))...));
+         this->used_ = true;
+      }
+   }
+
    template
    void priv_copy_some_and_update(const index_tuple&, 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(!used_){
-            *p = boost::move(T(::boost::container::containers_detail::stored_ref::forward(get(args_))...));
-            used_ = true;
+         if(!this->used_){
+            *p = boost::move(value_type(
+               ::boost::container::container_detail::stored_ref::forward(get(this->args_))...));
+            this->used_ = true;
          }
       }
    }
-   tuple args_;
-   bool used_;
 };
 
-}}}   //namespace boost { namespace container { namespace containers_detail {
+}}}   //namespace boost { namespace container { namespace container_detail {
 
-#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
 #include  
 #include 
 
 namespace boost {
 namespace container { 
-namespace containers_detail {
+namespace container_detail {
 
-//This class template will adapt each FwIt types to advanced_insert_aux_int
-template
-struct advanced_insert_aux_emplace
-   :  public advanced_insert_aux_int
-{
-   typedef typename advanced_insert_aux_int::difference_type difference_type;
-   advanced_insert_aux_emplace()
-      :  used_(false)
-   {}
-
-   ~advanced_insert_aux_emplace()
-   {}
-
-   virtual void copy_all_to(Iterator p)
-   {
-      if(!used_){
-         value_initv;
-         *p = boost::move(v.m_t);
-         used_ = true;
-      }
-   }
-
-   virtual void uninitialized_copy_all_to(Iterator p)
-   {
-      if(!used_){
-         new(containers_detail::get_pointer(&*p))T();
-         used_ = true;
-      }
-   }
-
-   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(!used_){
-            new(containers_detail::get_pointer(&*p))T();
-            used_ = true;
-         }
-      }
-   }
-
-   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(!used_){
-            value_initv;
-            *p = boost::move(v.m_t);
-            used_ = true;
-         }
-      }
-   }
-   private:
-   bool used_;
-};
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                     \
-   template                \
-   struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)                \
-      :  public advanced_insert_aux_int                                     \
-   {                                                                                   \
-      typedef typename advanced_insert_aux_int::difference_type difference_type;  \
-                                                                                       \
-      BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)                    \
-         ( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) )          \
-         : used_(false), BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {}     \
-                                                                                       \
-      virtual void copy_all_to(Iterator p)                                             \
-      {                                                                                \
-         if(!used_){                                                                   \
-            T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _));            \
-            *p = boost::move(v);                                                 \
-            used_ = true;                                                              \
-         }                                                                             \
-      }                                                                                \
-                                                                                       \
-      virtual void uninitialized_copy_all_to(Iterator p)                               \
-      {                                                                                \
-         if(!used_){                                                                   \
-            new(containers_detail::get_pointer(&*p))T                                             \
-               (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _));            \
-            used_ = true;                                                              \
-         }                                                                             \
-      }                                                                                \
-                                                                                       \
-      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(!used_){                                                                \
-               new(containers_detail::get_pointer(&*p))T                                          \
-                  (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _));         \
-               used_ = true;                                                           \
-            }                                                                          \
-         }                                                                             \
-      }                                                                                \
-                                                                                       \
-      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(!used_){                                                                \
-               T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _));         \
-               *p = boost::move(v);                                              \
-               used_ = true;                                                           \
-            }                                                                          \
-         }                                                                             \
-      }                                                                                \
-                                                                                       \
-      bool used_;                                                                      \
-      BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _)                       \
-   };                                                                                  \
+#define BOOST_PP_LOCAL_MACRO(n)                                                     \
+template        \
+struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_non_movable_emplace, n), arg)  \
+   :  public advanced_insert_aux_int                                      \
+{                                                                                   \
+   typedef boost::container::allocator_traits alloc_traits;                      \
+   typedef typename allocator_traits::size_type size_type;                       \
+   typedef typename allocator_traits::value_type value_type;                     \
+   typedef typename advanced_insert_aux_int::difference_type              \
+      difference_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, _)                   \
+    {}                                                                              \
+                                                                                    \
+   virtual void copy_remaining_to(Iterator)                                         \
+   {  BOOST_ASSERT(false);   }                                                      \
+                                                                                    \
+   virtual void uninitialized_copy_remaining_to(Iterator p)                         \
+   {                                                                                \
+      if(!used_){                                                                   \
+         alloc_traits::construct                                                    \
+            ( a_                                                                    \
+            , container_detail::to_raw_pointer(&*p)                                 \
+            BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)         \
+            );                                                                      \
+         used_ = true;                                                              \
+      }                                                                             \
+   }                                                                                \
+                                                                                    \
+   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(!used_){                                                                \
+            alloc_traits::construct                                                 \
+               ( a_                                                                 \
+               , container_detail::to_raw_pointer(&*p)                              \
+               BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)      \
+               );                                                                   \
+            used_ = true;                                                           \
+         }                                                                          \
+      }                                                                             \
+   }                                                                                \
+                                                                                    \
+   virtual void copy_some_and_update(Iterator, difference_type, bool)               \
+   {  BOOST_ASSERT(false);   }                                                      \
+                                                                                    \
+   A &a_;                                                                           \
+   bool used_;                                                                      \
+   BOOST_PP_REPEAT(n, BOOST_CONTAINER_PP_PARAM_DEFINE, _)                           \
+};                                                                                  \
+                                                                                    \
+template        \
+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) >                        \
+{                                                                                   \
+   typedef BOOST_PP_CAT(BOOST_PP_CAT(                                               \
+      advanced_insert_aux_non_movable_emplace, n), arg)                             \
+          base_t;                 \
+   typedef typename base_t::value_type       value_type;                            \
+   typedef typename base_t::difference_type  difference_type;                       \
+                                                                                    \
+   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, _) )   \
+    {}                                                                              \
+                                                                                    \
+   virtual void copy_remaining_to(Iterator p)                                       \
+   {                                                                                \
+      if(!this->used_){                                                             \
+         value_type v BOOST_PP_LPAREN_IF(n)                                         \
+            BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)                  \
+            BOOST_PP_RPAREN_IF(n);                                                  \
+         *p = boost::move(v);                                                       \
+         this->used_ = true;                                                        \
+      }                                                                             \
+   }                                                                                \
+                                                                                    \
+   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_){                                                          \
+            value_type v BOOST_PP_LPAREN_IF(n)                                      \
+                  BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)            \
+                BOOST_PP_RPAREN_IF(n);                                              \
+            *p = boost::move(v);                                                    \
+            this->used_ = true;                                                     \
+         }                                                                          \
+      }                                                                             \
+   }                                                                                \
+};                                                                                  \
 //!
 
-#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
 #include BOOST_PP_LOCAL_ITERATE()
 
-}}}   //namespace boost { namespace container { namespace containers_detail {
+}}}   //namespace boost { namespace container { namespace container_detail {
 
-#endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+#endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
 #include 
 
-#endif //#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
+#endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
diff --git a/include/boost/container/detail/algorithms.hpp b/include/boost/container/detail/algorithms.hpp
index 677bebe..f0e897c 100644
--- a/include/boost/container/detail/algorithms.hpp
+++ b/include/boost/container/detail/algorithms.hpp
@@ -10,8 +10,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP
-#define BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP
+#ifndef BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
+#define BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -23,7 +23,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include 
 #include 
@@ -33,56 +32,25 @@
 #include 
 
 namespace boost {
-namespace container { 
+namespace container {
 
-#if defined(BOOST_NO_RVALUE_REFERENCES)
-template
-struct has_own_construct_from_it
+template
+inline void construct_in_place(A &a, T* dest, InpIt source)
+{     boost::container::allocator_traits::construct(a, dest, *source);  }
+//#endif
+
+template
+inline void construct_in_place(A &a, T *dest, default_construct_iterator)
 {
-   static const bool value = false;
-};
-
-namespace containers_detail  {
-
-template
-inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::true_)
-{
-   T::construct(dest, *source);
+   boost::container::allocator_traits::construct(a, dest);
 }
 
-template
-inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::false_)
+template
+inline void construct_in_place(A &a, T *dest, emplace_iterator ei)
 {
-   new((void*)dest)T(*source);
+   ei.construct_in_place(a, dest);
 }
-
-}  //namespace containers_detail   {
-
-template
-inline void construct_in_place(T* dest, InpIt source)
-{
-   typedef containers_detail::bool_::value> boolean_t;
-   containers_detail::construct_in_place_impl(dest, source, boolean_t());
-}
-
-#else
-template
-inline void construct_in_place(T* dest, InpIt source)
-{     ::new((void*)dest)T(*source);   }
-#endif
-
-template
-inline void construct_in_place(T *dest, default_construct_iterator)
-{
-   ::new((void*)dest)T();
-}
-
-template
-inline void construct_in_place(T *dest, emplace_iterator ei)
-{
-   ei.construct_in_place(dest);
-}
-
+/*
 template
 struct optimize_assign
 {
@@ -118,7 +86,7 @@ struct optimize_copy
 {};
 
 template inline
-OutIt copy_n_dispatch(InIt first, typename std::iterator_traits::difference_type length, OutIt dest, containers_detail::bool_)
+OutIt copy_n_dispatch(InIt first, typename std::iterator_traits::difference_type length, OutIt dest, container_detail::bool_)
 {
    for (; length--; ++dest, ++first)
       *dest = *first;
@@ -126,7 +94,7 @@ OutIt copy_n_dispatch(InIt first, typename std::iterator_traits::differenc
 }
 
 template inline
-T *copy_n_dispatch(const T *first, typename std::iterator_traits::difference_type length, T *dest, containers_detail::bool_)
+T *copy_n_dispatch(const T *first, typename std::iterator_traits::difference_type length, T *dest, container_detail::bool_)
 {
    std::size_t size = length*sizeof(T);
    return (static_cast(std::memmove(dest, first, size))) + size;
@@ -136,14 +104,14 @@ template inline
 OutIt copy_n(InIt first, typename std::iterator_traits::difference_type length, OutIt dest)
 {
    const bool do_optimized_assign = optimize_assign::value;
-   return copy_n_dispatch(first, length, dest, containers_detail::bool_());
+   return copy_n_dispatch(first, length, dest, container_detail::bool_());
 }
 
 template inline
 FwdIt uninitialized_copy_n_dispatch
    (InIt first, 
     typename std::iterator_traits::difference_type count,
-    FwdIt dest, containers_detail::bool_)
+    FwdIt dest, container_detail::bool_)
 {
    typedef typename std::iterator_traits::value_type value_type;
    //Save initial destination position
@@ -153,14 +121,14 @@ FwdIt uninitialized_copy_n_dispatch
    BOOST_TRY{
       //Try to build objects
       for (; --new_count; ++dest, ++first){
-         construct_in_place(containers_detail::get_pointer(&*dest), first);
+         construct_in_place(container_detail::to_raw_pointer(&*dest), first);
       }
    }
    BOOST_CATCH(...){
       //Call destructors
       new_count = count - new_count;
       for (; new_count--; ++dest_init){
-         containers_detail::get_pointer(&*dest_init)->~value_type();
+         container_detail::to_raw_pointer(&*dest_init)->~value_type();
       }
       BOOST_RETHROW
    }
@@ -168,7 +136,7 @@ FwdIt uninitialized_copy_n_dispatch
    return dest;
 }
 template inline
-T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits::difference_type length, T *dest, containers_detail::bool_)
+T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits::difference_type length, T *dest, container_detail::bool_)
 {
    std::size_t size = length*sizeof(T);
    return (static_cast(std::memmove(dest, first, size))) + size;
@@ -181,7 +149,7 @@ FwdIt uninitialized_copy_n
     FwdIt dest)
 {
    const bool do_optimized_copy = optimize_copy::value;
-   return uninitialized_copy_n_dispatch(first, count, dest, containers_detail::bool_());
+   return uninitialized_copy_n_dispatch(first, count, dest, container_detail::bool_());
 }
 
 // uninitialized_copy_copy
@@ -199,17 +167,17 @@ FwdIt uninitialized_copy_copy
    }
    BOOST_CATCH(...){
       for(;result != mid; ++result){
-         containers_detail::get_pointer(&*result)->~value_type();
+         container_detail::to_raw_pointer(&*result)->~value_type();
       }
       BOOST_RETHROW
    }
    BOOST_CATCH_END
 }
-
+*/
 }  //namespace container { 
 }  //namespace boost {
 
 #include 
 
-#endif   //#ifndef BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP
+#endif   //#ifndef BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
 
diff --git a/include/boost/container/detail/allocation_type.hpp b/include/boost/container/detail/allocation_type.hpp
index b479cff..edad487 100644
--- a/include/boost/container/detail/allocation_type.hpp
+++ b/include/boost/container/detail/allocation_type.hpp
@@ -8,8 +8,8 @@
 //
 ///////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_ALLOCATION_TYPE_HPP
-#define BOOST_CONTAINERS_ALLOCATION_TYPE_HPP
+#ifndef BOOST_CONTAINER_ALLOCATION_TYPE_HPP
+#define BOOST_CONTAINER_ALLOCATION_TYPE_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -51,4 +51,4 @@ static const allocation_type zero_memory        = (allocation_type)zero_memory_v
 
 #include 
 
-#endif   //BOOST_CONTAINERS_ALLOCATION_TYPE_HPP
+#endif   //BOOST_CONTAINER_ALLOCATION_TYPE_HPP
diff --git a/include/boost/container/detail/config_begin.hpp b/include/boost/container/detail/config_begin.hpp
index 4be21ff..bd44daa 100644
--- a/include/boost/container/detail/config_begin.hpp
+++ b/include/boost/container/detail/config_begin.hpp
@@ -7,15 +7,15 @@
 // See http://www.boost.org/libs/container for documentation.
 //
 //////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED
-#define BOOST_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED
+#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
+#define BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
 #include 
 
-#endif   //BOOST_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED
+#endif   //BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
 
 #ifdef BOOST_MSVC
    #ifndef _CRT_SECURE_NO_DEPRECATE
-   #define  BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
+   #define  BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
    #define _CRT_SECURE_NO_DEPRECATE
    #endif
    #pragma warning (push)
diff --git a/include/boost/container/detail/config_end.hpp b/include/boost/container/detail/config_end.hpp
index 4713a66..b71fabc 100644
--- a/include/boost/container/detail/config_end.hpp
+++ b/include/boost/container/detail/config_end.hpp
@@ -9,8 +9,8 @@
 //////////////////////////////////////////////////////////////////////////////
 #if defined BOOST_MSVC
    #pragma warning (pop)
-   #ifdef BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
-   #undef BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
+   #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/include/boost/container/detail/destroyers.hpp b/include/boost/container/detail/destroyers.hpp
index 22fcf76..26ae089 100644
--- a/include/boost/container/detail/destroyers.hpp
+++ b/include/boost/container/detail/destroyers.hpp
@@ -10,8 +10,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DESTROYERS_HPP
-#define BOOST_CONTAINERS_DESTROYERS_HPP
+#ifndef BOOST_CONTAINER_DESTROYERS_HPP
+#define BOOST_CONTAINER_DESTROYERS_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -21,18 +21,20 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace boost {
 namespace container { 
-namespace containers_detail {
+namespace container_detail {
 
 //!A deleter for scoped_ptr that deallocates the memory
 //!allocated for an array of objects using a STL allocator.
 template 
 struct scoped_array_deallocator
 {
-   typedef typename Allocator::pointer    pointer;
-   typedef typename Allocator::size_type  size_type;
+   typedef boost::container::allocator_traits AllocTraits;
+   typedef typename AllocTraits::pointer    pointer;
+   typedef typename AllocTraits::size_type  size_type;
 
    scoped_array_deallocator(pointer p, Allocator& a, size_type length)
       : m_ptr(p), m_alloc(a), m_length(length) {}
@@ -52,8 +54,9 @@ struct scoped_array_deallocator
 template 
 struct null_scoped_array_deallocator
 {
-   typedef typename Allocator::pointer    pointer;
-   typedef typename Allocator::size_type  size_type;
+   typedef boost::container::allocator_traits AllocTraits;
+   typedef typename AllocTraits::pointer    pointer;
+   typedef typename AllocTraits::size_type  size_type;
 
    null_scoped_array_deallocator(pointer, Allocator&, size_type)
    {}
@@ -68,15 +71,13 @@ struct null_scoped_array_deallocator
 template 
 struct scoped_destructor_n
 {
-   typedef typename Allocator::pointer    pointer;
-   typedef typename Allocator::value_type value_type;
-   typedef typename Allocator::size_type  size_type;
+   typedef boost::container::allocator_traits AllocTraits;
+   typedef typename AllocTraits::pointer    pointer;
+   typedef typename AllocTraits::value_type value_type;
+   typedef typename AllocTraits::size_type  size_type;
 
-   pointer     m_p;
-   size_type   m_n;
-
-   scoped_destructor_n(pointer p, size_type n)
-      : m_p(p), m_n(n)
+   scoped_destructor_n(pointer p, Allocator& a, size_type n)
+      : m_p(p), m_a(a), m_n(n)
    {}
 
    void release()
@@ -88,10 +89,15 @@ struct scoped_destructor_n
    ~scoped_destructor_n()
    {
       if(!m_p) return;
-      value_type *raw_ptr = containers_detail::get_pointer(m_p);
+      value_type *raw_ptr = container_detail::to_raw_pointer(m_p);
       for(size_type i = 0; i < m_n; ++i, ++raw_ptr)
-         raw_ptr->~value_type();
+         AllocTraits::destroy(m_a, raw_ptr);
    }
+
+   private:
+   pointer     m_p;
+   Allocator & m_a;
+   size_type   m_n;
 };
 
 //!A deleter for scoped_ptr that destroys
@@ -99,10 +105,11 @@ struct scoped_destructor_n
 template 
 struct null_scoped_destructor_n
 {
-   typedef typename Allocator::pointer pointer;
-   typedef typename Allocator::size_type size_type;
+   typedef boost::container::allocator_traits AllocTraits;
+   typedef typename AllocTraits::pointer pointer;
+   typedef typename AllocTraits::size_type size_type;
 
-   null_scoped_destructor_n(pointer, size_type)
+   null_scoped_destructor_n(pointer, Allocator&, size_type)
    {}
 
    void increment_size(size_type)
@@ -112,43 +119,45 @@ struct null_scoped_destructor_n
    {}
 };
 
-template 
+template 
 class allocator_destroyer
 {
-   typedef typename A::value_type value_type;
-   typedef containers_detail::integral_constant::value>                           alloc_version;
-   typedef containers_detail::integral_constant     allocator_v1;
-   typedef containers_detail::integral_constant     allocator_v2;
+   typedef boost::container::allocator_traits AllocTraits;
+   typedef typename AllocTraits::value_type value_type;
+   typedef typename AllocTraits::pointer    pointer;
+   typedef container_detail::integral_constant::value>                           alloc_version;
+   typedef container_detail::integral_constant  allocator_v1;
+   typedef container_detail::integral_constant  allocator_v2;
 
    private:
-   A & a_;
+   Allocator & a_;
 
    private:
-   void priv_deallocate(const typename A::pointer &p, allocator_v1)
-   {  a_.deallocate(p, 1); }
+   void priv_deallocate(const pointer &p, allocator_v1)
+   {  AllocTraits::deallocate(a_,p, 1); }
 
-   void priv_deallocate(const typename A::pointer &p, allocator_v2)
+   void priv_deallocate(const pointer &p, allocator_v2)
    {  a_.deallocate_one(p); }
 
    public:
-   allocator_destroyer(A &a)
-      :  a_(a)
+   allocator_destroyer(Allocator &a)
+      : a_(a)
    {}
 
-   void operator()(const typename A::pointer &p)
-   {  
-      containers_detail::get_pointer(p)->~value_type();
+   void operator()(const pointer &p)
+   {
+      AllocTraits::destroy(a_, container_detail::to_raw_pointer(p));
       priv_deallocate(p, alloc_version());
    }
 };
 
 
-}  //namespace containers_detail { 
+}  //namespace container_detail { 
 }  //namespace container { 
 }  //namespace boost {
 
 #include 
 
-#endif   //#ifndef BOOST_CONTAINERS_DESTROYERS_HPP
+#endif   //#ifndef BOOST_CONTAINER_DESTROYERS_HPP
diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp
index 7cbc175..9ad5c0d 100644
--- a/include/boost/container/detail/flat_tree.hpp
+++ b/include/boost/container/detail/flat_tree.hpp
@@ -8,8 +8,8 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_FLAT_TREE_HPP
-#define BOOST_CONTAINERS_FLAT_TREE_HPP
+#ifndef BOOST_CONTAINER_FLAT_TREE_HPP
+#define BOOST_CONTAINER_FLAT_TREE_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -37,7 +37,7 @@ namespace boost {
 
 namespace container {
 
-namespace containers_detail {
+namespace container_detail {
 
 template
 class flat_tree_value_compare
@@ -47,6 +47,10 @@ class flat_tree_value_compare
    typedef Value              second_argument_type;
    typedef bool               return_type;
    public:     
+   flat_tree_value_compare()
+      : Compare()
+   {}
+
    flat_tree_value_compare(const Compare &pred) 
       : Compare(pred)
    {}
@@ -67,9 +71,9 @@ class flat_tree_value_compare
 template
 struct get_flat_tree_iterators
 {
-   typedef typename containers_detail::
+   typedef typename container_detail::
       vector_iterator                        iterator;
-   typedef typename containers_detail::
+   typedef typename container_detail::
       vector_const_iterator                  const_iterator;
    typedef std::reverse_iterator            reverse_iterator;
    typedef std::reverse_iterator      const_reverse_iterator;
@@ -90,23 +94,29 @@ class flat_tree
       //Inherit from value_compare to do EBO
       : public value_compare
    {
-      private:
       BOOST_COPYABLE_AND_MOVABLE(Data)
+
       public:
+      Data()
+         : value_compare(), m_vect()
+      {}
+
       Data(const Data &d)
          : value_compare(d), m_vect(d.m_vect)
       {}
-      Data(const Compare &comp,
-           const vector_t &vect) 
-         : value_compare(comp), m_vect(vect){}
 
-      Data(const value_compare &comp,
-           const vector_t &vect) 
-         : value_compare(comp), m_vect(vect){}
+      Data(BOOST_RV_REF(Data) d)
+         : value_compare(boost::move(d)), m_vect(boost::move(d.m_vect))
+      {}
+
+      Data(const Compare &comp) 
+         : value_compare(comp), m_vect()
+      {}
 
       Data(const Compare &comp,
            const allocator_t &alloc) 
-         : value_compare(comp), m_vect(alloc){}
+         : value_compare(comp), m_vect(alloc)
+      {}
 
       Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d)
       {
@@ -122,6 +132,13 @@ class flat_tree
          return *this;
       }
 
+      void swap(Data &d)
+      {
+         value_compare& mycomp    = *this, & othercomp = d;
+         container_detail::do_swap(mycomp, othercomp);
+         this->m_vect.swap(d.m_vect);
+      }
+
       vector_t m_vect;
    };
 
@@ -138,23 +155,30 @@ class flat_tree
    typedef Key                                        key_type;
    typedef Compare                                    key_compare;
    typedef typename vector_t::allocator_type          allocator_type;
-   typedef allocator_type                             stored_allocator_type;
-   typedef typename allocator_type::size_type         size_type;
-   typedef typename allocator_type::difference_type   difference_type;
+   typedef typename vector_t::size_type               size_type;
+   typedef typename vector_t::difference_type         difference_type;
    typedef typename vector_t::iterator                iterator;
    typedef typename vector_t::const_iterator          const_iterator;
-   typedef std::reverse_iterator            reverse_iterator;
-   typedef std::reverse_iterator      const_reverse_iterator;
-   
+   typedef typename vector_t::reverse_iterator        reverse_iterator;
+   typedef typename vector_t::const_reverse_iterator  const_reverse_iterator;
 
-   // allocation/deallocation
-   flat_tree(const Compare& comp     = Compare(), 
-             const allocator_type& a = allocator_type())
+   //!Standard extension
+   typedef allocator_type                             stored_allocator_type;
+
+   flat_tree()
+      : m_data()
+   { }
+
+   explicit flat_tree(const Compare& comp)
+      : m_data(comp)
+   { }
+
+   flat_tree(const Compare& comp, const allocator_type& a)
       : m_data(comp, a)
    { }
 
    flat_tree(const flat_tree& x) 
-      :  m_data(x.m_data, x.m_data.m_vect)
+      :  m_data(x.m_data)
    { }
 
    flat_tree(BOOST_RV_REF(flat_tree) x)
@@ -237,14 +261,7 @@ class flat_tree
    { return this->m_data.m_vect.max_size(); }
 
    void swap(flat_tree& other) 
-   {
-      value_compare& mycomp    = this->m_data;
-      value_compare& othercomp = other.m_data;
-      containers_detail::do_swap(mycomp, othercomp);
-      vector_t & myvect    = this->m_data.m_vect;
-      vector_t & othervect = other.m_data.m_vect;
-      myvect.swap(othervect);
-   }
+   {  this->m_data.swap(other.m_data);  }
 
    public:
    // insert/erase
@@ -332,7 +349,7 @@ class flat_tree
       priv_insert_equal(first, last, ItCat());
    }
 
-   #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    template 
    iterator emplace_unique(Args&&... args)
@@ -377,100 +394,69 @@ class flat_tree
       return priv_insert_commit(data, boost::move(val));
    }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
-
-   iterator emplace_unique()
-   {
-      containers_detail::value_init vval;
-      value_type &val = vval.m_t;
-      insert_commit_data data;
-      std::pair ret =
-         priv_insert_unique_prepare(val, data);
-      if(ret.second){
-         ret.first = priv_insert_commit(data, boost::move(val));
-      }
-      return ret.first;
-   }
-
-   iterator emplace_hint_unique(const_iterator hint)
-   {
-      containers_detail::value_init vval;
-      value_type &val = vval.m_t;
-      insert_commit_data data;
-      std::pair ret = priv_insert_unique_prepare(hint, val, data);
-      if(ret.second){
-         ret.first = priv_insert_commit(data, boost::move(val));
-      }
-      return ret.first;
-   }
-
-   iterator emplace_equal()
-   {
-      containers_detail::value_init vval;
-      value_type &val = vval.m_t;
-      iterator i = this->upper_bound(KeyOfValue()(val));
-      i = this->m_data.m_vect.insert(i, boost::move(val));
-      return i;
-   }
-
-   iterator emplace_hint_equal(const_iterator hint)
-   {
-      containers_detail::value_init vval;
-      value_type &val = vval.m_t;
-      insert_commit_data data;
-      priv_insert_equal_prepare(hint, val, data);
-      return priv_insert_commit(data, boost::move(val));
-   }
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    #define BOOST_PP_LOCAL_MACRO(n)                                                        \
-   template                                             \
-   iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))         \
+   BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+   iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))           \
    {                                                                                      \
-      value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));           \
+      BOOST_PP_EXPR_IF(BOOST_PP_NOT(n), container_detail::value_init<) value_type        \
+         BOOST_PP_EXPR_IF(BOOST_PP_NOT(n), >) vval BOOST_PP_LPAREN_IF(n)                  \
+            BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) BOOST_PP_RPAREN_IF(n); \
+      value_type &val = vval;                                                             \
       insert_commit_data data;                                                            \
       std::pair ret = priv_insert_unique_prepare(val, data);               \
       if(ret.second){                                                                     \
-         ret.first = priv_insert_commit(data, boost::move(val)); \
+         ret.first = priv_insert_commit(data, boost::move(val));                          \
       }                                                                                   \
       return ret.first;                                                                   \
    }                                                                                      \
                                                                                           \
-   template                                             \
-   iterator emplace_hint_unique(const_iterator hint,                                      \
-      BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                              \
+   BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+   iterator emplace_hint_unique(const_iterator hint                                       \
+                        BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _))     \
    {                                                                                      \
-      value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));           \
+      BOOST_PP_EXPR_IF(BOOST_PP_NOT(n), container_detail::value_init<) value_type        \
+         BOOST_PP_EXPR_IF(BOOST_PP_NOT(n), >) vval BOOST_PP_LPAREN_IF(n)                  \
+            BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) BOOST_PP_RPAREN_IF(n); \
+      value_type &val = vval;                                                             \
       insert_commit_data data;                                                            \
       std::pair ret = priv_insert_unique_prepare(hint, val, data);         \
       if(ret.second){                                                                     \
-         ret.first = priv_insert_commit(data, boost::move(val));        \
+         ret.first = priv_insert_commit(data, boost::move(val));                          \
       }                                                                                   \
       return ret.first;                                                                   \
    }                                                                                      \
                                                                                           \
-   template                                             \
-   iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))          \
+   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, _))            \
    {                                                                                      \
-      value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));           \
+      BOOST_PP_EXPR_IF(BOOST_PP_NOT(n), container_detail::value_init<) value_type        \
+         BOOST_PP_EXPR_IF(BOOST_PP_NOT(n), >) vval BOOST_PP_LPAREN_IF(n)                  \
+            BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) BOOST_PP_RPAREN_IF(n); \
+      value_type &val = vval;                                                             \
       iterator i = this->upper_bound(KeyOfValue()(val));                                  \
-      i = this->m_data.m_vect.insert(i, boost::move(val));       \
+      i = this->m_data.m_vect.insert(i, boost::move(val));                                \
       return i;                                                                           \
    }                                                                                      \
                                                                                           \
-   template                                             \
-   iterator emplace_hint_equal(const_iterator hint,                                       \
-      BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                              \
+   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, _))       \
    {                                                                                      \
-      value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));           \
+      BOOST_PP_EXPR_IF(BOOST_PP_NOT(n), container_detail::value_init<) value_type        \
+         BOOST_PP_EXPR_IF(BOOST_PP_NOT(n), >) vval BOOST_PP_LPAREN_IF(n)                  \
+            BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) BOOST_PP_RPAREN_IF(n); \
+      value_type &val = vval;                                                             \
       insert_commit_data data;                                                            \
       priv_insert_equal_prepare(hint, val, data);                                         \
-      return priv_insert_commit(data, boost::move(val));                \
+      return priv_insert_commit(data, boost::move(val));                                  \
    }                                                                                      \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    iterator erase(const_iterator position)
    {  return this->m_data.m_vect.erase(position);  }
@@ -571,8 +557,6 @@ class flat_tree
       //         insert val before pos
       //      else
       //         insert val before upper_bound(val)
-      //   else if pos+1 == end || val <= *(pos+1)
-      //      insert val after pos
       //   else
       //      insert val before lower_bound(val)
       const value_compare &value_comp = this->m_data;
@@ -586,10 +570,6 @@ class flat_tree
                this->priv_upper_bound(this->cbegin(), pos, KeyOfValue()(val));
          }
       }
-      //Works, but increases code complexity
-      //else if (++pos == this->end() || !value_comp(*pos, val)){
-      //   return this->m_data.m_vect.insert(pos, val);
-      //}
       else{
          data.position = 
             this->priv_lower_bound(pos, this->cend(), KeyOfValue()(val));
@@ -838,7 +818,7 @@ swap(flat_tree& x,
      flat_tree& y)
    {  x.swap(y);  }
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 
 }  //namespace container {
 /*
@@ -846,7 +826,7 @@ swap(flat_tree& x,
 //!specialization for optimizations
 template 
-struct has_trivial_destructor_after_move >
+struct has_trivial_destructor_after_move >
 {
    static const bool value = has_trivial_destructor::value && has_trivial_destructor::value;
 };
@@ -855,4 +835,4 @@ struct has_trivial_destructor_after_move
 
-#endif // BOOST_CONTAINERS_FLAT_TREE_HPP
+#endif // BOOST_CONTAINER_FLAT_TREE_HPP
diff --git a/include/boost/container/detail/function_detector.hpp b/include/boost/container/detail/function_detector.hpp
new file mode 100644
index 0000000..c37c766
--- /dev/null
+++ b/include/boost/container/detail/function_detector.hpp
@@ -0,0 +1,88 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga  2009-2011.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+/////////////////////////////////////////////////////////////////////////////
+//  This code was modified from the code posted by Alexandre Courpron in his
+//  article "Interface Detection" in The Code Project:
+//  http://www.codeproject.com/KB/architecture/Detector.aspx
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2007 Alexandre Courpron
+//
+// Permission to use, copy, modify, redistribute and sell this software, 
+// provided that this copyright notice appears on all copies of the software.
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
+#define BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
+
+#include 
+
+namespace boost {
+namespace container {
+namespace function_detector {
+
+    typedef char NotFoundType;
+    struct StaticFunctionType { NotFoundType x [2]; };
+    struct NonStaticFunctionType { NotFoundType x [3]; };
+
+    enum
+         { NotFound          = 0,
+           StaticFunction    = sizeof( StaticFunctionType )    - sizeof( NotFoundType ),
+           NonStaticFunction = sizeof( NonStaticFunctionType ) - sizeof( NotFoundType )
+         };
+
+}  //namespace boost {
+}  //namespace container {
+}  //namespace function_detector {
+
+#define BOOST_CONTAINER_CREATE_FUNCTION_DETECTOR(Identifier, InstantiationKey) \
+   namespace boost { \
+   namespace container { \
+   namespace function_detector { \
+   template < class T, \
+            class NonStaticType, \
+            class NonStaticConstType, \
+            class StaticType > \
+   class DetectMember_##InstantiationKey_##Identifier { \
+      template < NonStaticType > \
+      struct TestNonStaticNonConst ; \
+      \
+      template < NonStaticConstType > \
+      struct TestNonStaticConst ; \
+      \
+      template < StaticType > \
+      struct TestStatic ; \
+      \
+      template  \
+      static NonStaticFunctionType Test( TestNonStaticNonConst<&U::Identifier>*, int ); \
+      \
+      template  \
+      static NonStaticFunctionType Test( TestNonStaticConst<&U::Identifier>*, int ); \
+      \
+      template  \
+      static StaticFunctionType Test( TestStatic<&U::Identifier>*, int ); \
+      \
+      template  \
+      static NotFoundType Test( ... ); \
+   public : \
+      static const int check = NotFound + (sizeof(Test(0, 0)) - sizeof(NotFoundType));\
+   };\
+}}} //namespace boost::container::function_detector { 
+
+#define BOOST_CONTAINER_DETECT_FUNCTION(Class, InstantiationKey, ReturnType, Identifier, Params) \
+    ::boost::container::function_detector::DetectMember_##InstantiationKey_##Identifier< Class,\
+                                         ReturnType (Class::*)Params,\
+                                         ReturnType (Class::*)Params const,\
+                                         ReturnType (*)Params \
+                                       >::check
+
+#include 
+
+#endif   //@ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
diff --git a/include/boost/container/detail/iterators.hpp b/include/boost/container/detail/iterators.hpp
index a83b472..899cbe4 100644
--- a/include/boost/container/detail/iterators.hpp
+++ b/include/boost/container/detail/iterators.hpp
@@ -11,8 +11,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_ITERATORS_HPP
-#define BOOST_CONTAINERS_DETAIL_ITERATORS_HPP
+#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
+#define BOOST_CONTAINER_DETAIL_ITERATORS_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -21,8 +21,9 @@
 #include "config_begin.hpp"
 #include 
 #include 
+#include 
 
-#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 #include 
 #include 
 #else
@@ -368,7 +369,7 @@ class repeat_iterator
    {  return m_num - other.m_num;   }
 };
 
-template 
+template 
 class emplace_iterator
   : public std::iterator
       
@@ -377,7 +378,7 @@ class emplace_iterator
 
    public:
    typedef Difference difference_type;
-   explicit emplace_iterator(E&e)
+   explicit emplace_iterator(EmplaceFunctor&e)
       :  m_num(1), m_pe(&e){}
 
    emplace_iterator()
@@ -453,12 +454,13 @@ class emplace_iterator
    const T* operator->() const
    { return &(dereference()); }
 
-   void construct_in_place(T* ptr)
-   {  (*m_pe)(ptr);  }
+   template
+   void construct_in_place(A &a, T* ptr)
+   {  (*m_pe)(a, ptr);  }
 
    private:
    difference_type m_num;
-   E *            m_pe;
+   EmplaceFunctor *            m_pe;
 
    void increment()
    { --m_num; }
@@ -485,54 +487,54 @@ class emplace_iterator
    {  return difference_type(m_num - other.m_num);   }
 };
 
-#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
-template
+template
 struct emplace_functor
 {
-   typedef typename containers_detail::build_number_seq::type index_tuple_t;
+   typedef typename container_detail::build_number_seq::type index_tuple_t;
 
    emplace_functor(Args&&... args)
       : args_(args...)
    {}
 
-   void operator()(T *ptr)
-   {  emplace_functor::inplace_impl(ptr, index_tuple_t());  }
+   template
+   void operator()(A &a, T *ptr)
+   {  emplace_functor::inplace_impl(a, ptr, index_tuple_t());  }
 
-   template
-   void inplace_impl(T* ptr, const containers_detail::index_tuple&)
-   {  ::new(ptr) T(containers_detail::stored_ref::forward(containers_detail::get(args_))...); }
+   template
+   void inplace_impl(A &a, T* ptr, const container_detail::index_tuple&)
+   {
+      allocator_traits::construct
+         (a, ptr, container_detail::stored_ref::forward
+          (container_detail::get(args_))...);
+   }
 
-   containers_detail::tuple args_;
+   container_detail::tuple args_;
 };
 
 #else
 
-template
-struct emplace_functor
-{
-   emplace_functor()
-   {}
-   void operator()(T *ptr)
-   {  new(ptr) T();  }
-};
-
 #define BOOST_PP_LOCAL_MACRO(n)                                                        \
-   template                                \
+   BOOST_PP_EXPR_IF(n, template <)                                                     \
+      BOOST_PP_ENUM_PARAMS(n, class P)                                                 \
+         BOOST_PP_EXPR_IF(n, >)                                                        \
    struct BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg)                          \
    {                                                                                   \
       BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg)                              \
-         ( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) )                       \
-      :  BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {}                       \
+         ( BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _) )                       \
+      BOOST_PP_EXPR_IF(n, :) BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_INIT, _){}    \
                                                                                        \
-      void operator()(T *ptr)                                                          \
+      template                                                       \
+      void operator()(A &a, T *ptr)                                                    \
       {                                                                                \
-         new(ptr)T (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _));          \
+         allocator_traits::construct                                                \
+            (a, ptr BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) );\
       }                                                                                \
-      BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _)                         \
+      BOOST_PP_REPEAT(n, BOOST_CONTAINER_PP_PARAM_DEFINE, _)                         \
    };                                                                                  \
    //!
-#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
 #include BOOST_PP_LOCAL_ITERATE()
 
 #endif
@@ -542,5 +544,5 @@ struct emplace_functor
 
 #include 
 
-#endif   //#ifndef BOOST_CONTAINERS_DETAIL_ITERATORS_HPP
+#endif   //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
 
diff --git a/include/boost/container/detail/math_functions.hpp b/include/boost/container/detail/math_functions.hpp
index c7c443c..4613573 100644
--- a/include/boost/container/detail/math_functions.hpp
+++ b/include/boost/container/detail/math_functions.hpp
@@ -22,7 +22,7 @@
 
 namespace boost {
 namespace container {
-namespace containers_detail {
+namespace container_detail {
 
 // Greatest common divisor and least common multiple
 
@@ -104,7 +104,7 @@ inline std::size_t floor_log2 (std::size_t x)
    return log2;
 }
 
-} // namespace containers_detail
+} // namespace container_detail
 } // namespace container
 } // namespace boost
 
diff --git a/include/boost/container/detail/mpl.hpp b/include/boost/container/detail/mpl.hpp
index d0741fa..e2ebcf7 100644
--- a/include/boost/container/detail/mpl.hpp
+++ b/include/boost/container/detail/mpl.hpp
@@ -10,8 +10,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP
-#define BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP
+#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
+#define BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -21,7 +21,7 @@
 
 namespace boost {
 namespace container { 
-namespace containers_detail {
+namespace container_detail {
 
 template 
 struct integral_constant
@@ -34,6 +34,7 @@ template< bool C_ >
 struct bool_ : integral_constant
 {
    static const bool value = C_;
+   operator bool() const { return bool_::value; }
 };
 
 typedef bool_        true_;
@@ -147,9 +148,9 @@ struct ls_zeros<1>
    static const std::size_t value = 0;
 };
 
-}  //namespace containers_detail { 
+}  //namespace container_detail { 
 }  //namespace container { 
 }  //namespace boost {
 
-#endif   //#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP
+#endif   //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
 
diff --git a/include/boost/container/detail/multiallocation_chain.hpp b/include/boost/container/detail/multiallocation_chain.hpp
index 52e0cb7..a67fd77 100644
--- a/include/boost/container/detail/multiallocation_chain.hpp
+++ b/include/boost/container/detail/multiallocation_chain.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
-#define BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
+#ifndef BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
+#define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
 
 #include "config_begin.hpp"
 #include 
@@ -17,13 +17,13 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 
 namespace boost {
 namespace container {
-namespace containers_detail {
+namespace container_detail {
 
 template
 class basic_multiallocation_chain
@@ -33,8 +33,10 @@ class basic_multiallocation_chain
                         ,bi::link_mode
                         > node;
 
-   typedef typename boost::pointer_to_other::type   char_ptr;
-   typedef typename std::iterator_traits::difference_type    difference_type;
+   typedef typename boost::intrusive::pointer_traits
+      ::template rebind_pointer::type    char_ptr;
+   typedef typename boost::intrusive::
+      pointer_traits::difference_type             difference_type;
 
    typedef bi::slist< node
                     , bi::linear
@@ -44,7 +46,7 @@ class basic_multiallocation_chain
    slist_impl_t slist_impl_;
 
    static node & to_node(VoidPointer p)
-   {  return *static_cast(static_cast(containers_detail::get_pointer(p))); }
+   {  return *static_cast(static_cast(container_detail::to_raw_pointer(p))); }
 
    BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
 
@@ -140,7 +142,7 @@ class basic_multiallocation_chain
 template
 struct cast_functor
 {
-   typedef typename containers_detail::add_reference::type result_type;
+   typedef typename container_detail::add_reference::type result_type;
    template
    result_type operator()(U &ptr) const
    {  return *static_cast(static_cast(&ptr));  }
@@ -154,18 +156,18 @@ class transform_multiallocation_chain
 
    MultiallocationChain   holder_;
    typedef typename MultiallocationChain::void_pointer   void_pointer;
-   typedef typename boost::pointer_to_other
-      ::type                            pointer;
+   typedef typename boost::intrusive::pointer_traits
+      ::template rebind_pointer::type   pointer;
 
    static pointer cast(void_pointer p)
    {
-      return pointer(static_cast(containers_detail::get_pointer(p)));
+      return pointer(static_cast(container_detail::to_raw_pointer(p)));
    }
 
    public:
    typedef transform_iterator
       < typename MultiallocationChain::iterator
-      , containers_detail::cast_functor  >                 iterator;
+      , container_detail::cast_functor  >                 iterator;
    typedef typename MultiallocationChain::size_type           size_type;
 
    transform_multiallocation_chain()
@@ -243,10 +245,10 @@ class transform_multiallocation_chain
 
 }}}
 
-// namespace containers_detail {
+// namespace container_detail {
 // namespace container {
 // namespace boost {
 
 #include 
 
-#endif   //BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
+#endif   //BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp
index f2e88ef..9b0a0a5 100644
--- a/include/boost/container/detail/node_alloc_holder.hpp
+++ b/include/boost/container/detail/node_alloc_holder.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
-#define BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
+#ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
+#define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -27,10 +27,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
-#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
+#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
 #include 
 #endif
 
@@ -39,19 +40,20 @@
 
 namespace boost {
 namespace container {
-namespace containers_detail {
+namespace container_detail {
 
 //!A deleter for scoped_ptr that deallocates the memory
 //!allocated for an object using a STL allocator.
-template 
+template 
 struct scoped_deallocator
 {
-   typedef typename Allocator::pointer pointer;
-   typedef containers_detail::integral_constant::value>                   alloc_version;
-   typedef containers_detail::integral_constant     allocator_v1;
-   typedef containers_detail::integral_constant     allocator_v2;
+   typedef allocator_traits allocator_traits_type;
+   typedef typename allocator_traits_type::pointer pointer;
+   typedef container_detail::integral_constant::value>                   alloc_version;
+   typedef container_detail::integral_constant     allocator_v1;
+   typedef container_detail::integral_constant     allocator_v2;
 
    private:
    void priv_deallocate(allocator_v1)
@@ -65,9 +67,9 @@ struct scoped_deallocator
    public:
 
    pointer     m_ptr;
-   Allocator&  m_alloc;
+   A&  m_alloc;
 
-   scoped_deallocator(pointer p, Allocator& a)
+   scoped_deallocator(pointer p, A& a)
       : m_ptr(p), m_alloc(a)
    {}
 
@@ -88,7 +90,8 @@ struct scoped_deallocator
 template 
 class allocator_destroyer_and_chain_builder
 {
-   typedef typename A::value_type value_type;
+   typedef allocator_traits allocator_traits_type;
+   typedef typename allocator_traits_type::value_type value_type;
    typedef typename A::multiallocation_chain    multiallocation_chain;
 
    A & a_;
@@ -100,17 +103,17 @@ class allocator_destroyer_and_chain_builder
    {}
 
    void operator()(const typename A::pointer &p)
-   {  
-      value_type *vp = containers_detail::get_pointer(p);
-      vp->~value_type();
-      c_.push_front(vp);
+   {
+      allocator_traits::destroy(a_, container_detail::to_raw_pointer(p));
+      c_.push_front(p);
    }
 };
 
 template 
 class allocator_multialloc_chain_node_deallocator
 {
-   typedef typename A::value_type value_type;
+   typedef allocator_traits 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 chain_builder;
 
@@ -132,7 +135,6 @@ class allocator_multialloc_chain_node_deallocator
    }
 };
 
-
 template
 struct node_compare
    :  private ValueCompare
@@ -155,70 +157,90 @@ struct node_compare
    {  return ValueCompare::operator()(a.get_data(), b.get_data());  }
 };
 
-template
+template
 struct node_alloc_holder
 {
-   typedef node_alloc_holder                self_t;
-   typedef typename A::value_type                     value_type;
-   typedef typename ICont::value_type                 Node;
-   typedef typename A::template rebind::other   NodeAlloc;
-   typedef A                                          ValAlloc;
-   typedef typename NodeAlloc::pointer                NodePtr;
-   typedef containers_detail::scoped_deallocator      Deallocator;
-   typedef typename NodeAlloc::size_type              size_type;
-   typedef typename NodeAlloc::difference_type        difference_type;
-   typedef containers_detail::integral_constant     allocator_v1;
-   typedef containers_detail::integral_constant     allocator_v2;
-   typedef containers_detail::integral_constant                                    allocator_traits_type;
+   typedef node_alloc_holder                            self_t;
+   typedef typename allocator_traits_type::value_type             value_type;
+   typedef typename ICont::value_type                             Node;
+   typedef typename allocator_traits_type::template
+      portable_rebind_alloc::type                           NodeAlloc;
+   typedef allocator_traits                            node_allocator_traits_type;
+   typedef A                                                      ValAlloc;
+   typedef typename node_allocator_traits_type::pointer           NodePtr;
+   typedef container_detail::scoped_deallocator        Deallocator;
+   typedef typename node_allocator_traits_type::size_type         size_type;
+   typedef typename node_allocator_traits_type::difference_type   difference_type;
+   typedef container_detail::integral_constant       allocator_v1;
+   typedef container_detail::integral_constant       allocator_v2;
+   typedef container_detail::integral_constant::value>                   alloc_version;
    typedef typename ICont::iterator                   icont_iterator;
    typedef typename ICont::const_iterator             icont_citerator;
    typedef allocator_destroyer             Destroyer;
+   typedef allocator_traits                NodeAllocTraits;
 
    private:
    BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder)
 
    public:
 
-   node_alloc_holder(const ValAlloc &a) 
+   //Constructors for sequence containers
+   node_alloc_holder() 
+      : members_()
+   {}
+
+   explicit node_alloc_holder(const ValAlloc &a) 
       : members_(a)
    {}
 
-   node_alloc_holder(const node_alloc_holder &other)
-      : members_(other.node_alloc())
+   explicit node_alloc_holder(const node_alloc_holder &x)
+      : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
    {}
 
-   node_alloc_holder(BOOST_RV_REF(node_alloc_holder) other)
-      : members_(boost::move(other.node_alloc()))
-   {  this->swap(other);  }
+   explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x)
+      : members_(boost::move(x.node_alloc()))
+   {  this->icont().swap(x.icont());  }
 
-   node_alloc_holder & operator=(BOOST_COPY_ASSIGN_REF(node_alloc_holder) other)
-   {  members_.assign(other.node_alloc());   }
-
-   node_alloc_holder & operator=(BOOST_RV_REF(node_alloc_holder) other)
-   {  members_.assign(other.node_alloc());   }
-
-   template
-   node_alloc_holder(const ValAlloc &a, const Pred &c) 
-      : members_(a, typename ICont::value_compare(c))
+   //Constructors for associative containers
+   explicit node_alloc_holder(const ValAlloc &a, const Pred &c) 
+      : members_(a, c)
    {}
 
-   template
-   node_alloc_holder(BOOST_RV_REF(ValAlloc) a, const Pred &c) 
-      : members_(a, typename ICont::value_compare(c))
+   explicit node_alloc_holder(const node_alloc_holder &x, const Pred &c)
+      : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c)
    {}
 
-   template
-   node_alloc_holder(const node_alloc_holder &other, const Pred &c)
-      : members_(other.node_alloc(), typename ICont::value_compare(c))
+   explicit node_alloc_holder(const Pred &c)
+      : members_(c)
    {}
 
+   //helpers for move assignments
+   explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const Pred &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_ flag;
+      container_detail::assign_alloc( static_cast(this->members_)
+                                    , static_cast(x.members_), flag);
+   }
+
+   void move_assign_alloc( node_alloc_holder &x)
+   {
+      container_detail::bool_ flag;
+      container_detail::move_alloc( static_cast(this->members_)
+                                  , static_cast(x.members_), flag);
+   }
+
    ~node_alloc_holder()
    {  this->clear(alloc_version()); }
 
    size_type max_size() const
-   {  return this->node_alloc().max_size();  }
+   {  return allocator_traits_type::max_size(this->node_alloc());  }
 
    NodePtr allocate_one()
    {  return this->allocate_one(alloc_version());   }
@@ -229,131 +251,100 @@ struct node_alloc_holder
    NodePtr allocate_one(allocator_v2)
    {  return this->node_alloc().allocate_one();   }
 
-   void deallocate_one(NodePtr p)
+   void deallocate_one(const NodePtr &p)
    {  return this->deallocate_one(p, alloc_version());   }
 
-   void deallocate_one(NodePtr p, allocator_v1)
+   void deallocate_one(const NodePtr &p, allocator_v1)
    {  this->node_alloc().deallocate(p, 1);   }
 
-   void deallocate_one(NodePtr p, allocator_v2)
+   void deallocate_one(const NodePtr &p, allocator_v2)
    {  this->node_alloc().deallocate_one(p);   }
-
-   template
-   static void construct(const NodePtr &ptr,
+/*
+   template
+   static void construct(A &a, const NodePtr &ptr,
       BOOST_RV_REF_2_TEMPL_ARGS(std::pair, Convertible1, Convertible2) value)
-   {  
+   {
       typedef typename Node::hook_type                hook_type;
       typedef typename Node::value_type::first_type   first_type;
       typedef typename Node::value_type::second_type  second_type;
-      Node *nodeptr = containers_detail::get_pointer(ptr);
+      Node *nodeptr = container_detail::to_raw_pointer(ptr);
 
       //Hook constructor does not throw
-      new(static_cast(nodeptr))hook_type();
+      allocator_traits::construct(a, static_cast(nodeptr));
+
       //Now construct pair members_holder
       value_type *valueptr = &nodeptr->get_data();
-      new((void*)&valueptr->first) first_type(boost::move(value.first));
+      allocator_traits::construct(a, &valueptr->first, boost::move(value.first));
       BOOST_TRY{
-         new((void*)&valueptr->second) second_type(boost::move(value.second));
+         allocator_traits::construct(a, &valueptr->second, boost::move(value.second));
       }
       BOOST_CATCH(...){
-         valueptr->first.~first_type();
-         static_cast(nodeptr)->~hook_type();
+         allocator_traits::destroy(a, &valueptr->first);
          BOOST_RETHROW
       }
       BOOST_CATCH_END
    }
-
-   static void destroy(const NodePtr &ptr)
-   {  containers_detail::get_pointer(ptr)->~Node();  }
-
-   Deallocator create_node_and_deallocator()
-   {
-      return Deallocator(this->allocate_one(), this->node_alloc());
+*/
+   #ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+/*
+   template
+   static void construct(A &a, const NodePtr &ptr, Args &&...args)
+   {  
    }
-
-   #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
-
-   template
-   static void construct(const NodePtr &ptr, Args &&...args)
-   {  new((void*)containers_detail::get_pointer(ptr)) Node(boost::forward(args)...);  }
-
+*/
    template
    NodePtr create_node(Args &&...args)
    {
       NodePtr p = this->allocate_one();
       Deallocator node_deallocator(p, this->node_alloc());
-      self_t::construct(p, boost::forward(args)...);
+      allocator_traits::construct
+         (this->node_alloc(), container_detail::to_raw_pointer(p), boost::forward(args)...);
       node_deallocator.release();
       return (p);
    }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
-
-   static void construct(const NodePtr &ptr)
-   {  new((void*)containers_detail::get_pointer(ptr)) Node();  }
-
-   NodePtr create_node()
-   {
-      NodePtr p = this->allocate_one();
-      Deallocator node_deallocator(p, this->node_alloc());
-      self_t::construct(p);
-      node_deallocator.release();
-      return (p);
-   }
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                           \
-   template                                                \
-   void construct(const NodePtr &ptr, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
-   {                                                                                         \
-      new((void*)containers_detail::get_pointer(ptr))                                                   \
-      Node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                        \
-   }                                                                                         \
-   //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
-   #include BOOST_PP_LOCAL_ITERATE()
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    #define BOOST_PP_LOCAL_MACRO(n)                                                        \
-   template                                             \
-   NodePtr create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))             \
+                                                                                          \
+   BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+   NodePtr create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                \
    {                                                                                      \
       NodePtr p = this->allocate_one();                                                   \
       Deallocator node_deallocator(p, this->node_alloc());                                \
-      self_t::construct(p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));     \
+      allocator_traits::construct                                              \
+         (this->node_alloc(), container_detail::to_raw_pointer(p)                         \
+            BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));              \
       node_deallocator.release();                                                         \
       return (p);                                                                         \
    }                                                                                      \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    template
-   NodePtr create_node_from_it(It it)
+   NodePtr create_node_from_it(const It &it)
    {
       NodePtr p = this->allocate_one();
       Deallocator node_deallocator(p, this->node_alloc());
-      ::boost::container::construct_in_place(containers_detail::get_pointer(p), it);
+      ::boost::container::construct_in_place(this->node_alloc(), container_detail::to_raw_pointer(p), it);
       node_deallocator.release();
       return (p);
    }
 
-   void destroy_node(NodePtr node)
+   void destroy_node(const NodePtr &nodep)
    {
-      self_t::destroy(node);
-      this->deallocate_one(node);
+      allocator_traits::destroy(this->node_alloc(), container_detail::to_raw_pointer(nodep));
+      this->deallocate_one(nodep);
    }
 
    void swap(node_alloc_holder &x)
    {
-      NodeAlloc& this_alloc   = this->node_alloc();
-      NodeAlloc& other_alloc  = x.node_alloc();
-
-      if (this_alloc != other_alloc){
-         containers_detail::do_swap(this_alloc, other_alloc);
-      }
-
       this->icont().swap(x.icont());
+      container_detail::bool_ flag;
+      container_detail::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
    }
 
    template
@@ -369,11 +360,11 @@ struct node_alloc_holder
          Node *p = 0;
          BOOST_TRY{
                for(difference_type i = 0; i < n; ++i, ++beg, --constructed){
-               p = containers_detail::get_pointer(mem.front());
+               p = container_detail::to_raw_pointer(mem.front());
                mem.pop_front();
                //This can throw
                constructed = 0;
-               boost::container::construct_in_place(p, beg);
+               boost::container::construct_in_place(this->node_alloc(), p, beg);
                ++constructed;
                //This can throw in some containers (predicate might throw)
                inserter(*p);
@@ -381,7 +372,7 @@ struct node_alloc_holder
          }
          BOOST_CATCH(...){
             if(constructed){
-               this->destroy(p);
+               allocator_traits::destroy(this->node_alloc(), container_detail::to_raw_pointer(p));
             }
             this->node_alloc().deallocate_individual(boost::move(mem));
             BOOST_RETHROW
@@ -404,10 +395,10 @@ struct node_alloc_holder
          this->node_alloc().deallocate_individual(boost::move(chain));
    }
 
-   icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v1)
+   icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v1)
    {  return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); }
 
-   icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v2)
+   icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v2)
    {
       allocator_multialloc_chain_node_deallocator chain_holder(this->node_alloc());
       return this->icont().erase_and_dispose(first, last, chain_holder.get_chain_builder());
@@ -437,44 +428,38 @@ struct node_alloc_holder
       node_alloc_holder &m_holder;
    };
 
-   struct destroyer
-   {
-      destroyer(node_alloc_holder &holder)
-         :  m_holder(holder)
-      {}
-
-      void operator()(NodePtr n) const
-      {  m_holder.destroy_node(n);  }
-
-      node_alloc_holder &m_holder;
-   };
-
    struct members_holder
       :  public NodeAlloc
    {
       private:
       members_holder(const members_holder&);
+      members_holder & operator=(const members_holder&);
 
       public:
-      template
-      members_holder(const ConvertibleToAlloc &c2alloc)
-         :  NodeAlloc(c2alloc)
-      {}
-
-      template
-      members_holder(const ConvertibleToAlloc &c2alloc, const Pred &c)
-         :  NodeAlloc(c2alloc), m_icont(c)
+      members_holder()
+         : NodeAlloc(), m_icont()
       {}
 
       template
-      void assign (const ConvertibleToAlloc &c2alloc)
-      {
-         NodeAlloc::operator=(c2alloc);
-      }
+      explicit members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc)
+         :  NodeAlloc(boost::forward(c2alloc))
+         , m_icont()
+      {}
+
+      template
+      members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const Pred &c)
+         :  NodeAlloc(boost::forward(c2alloc))
+         , m_icont(typename ICont::value_compare(c))
+      {}
+
+      explicit members_holder(const Pred &c)
+         : NodeAlloc()
+         , m_icont(typename ICont::value_compare(c))
+      {}
 
       //The intrusive container
       ICont m_icont;
-   } members_;
+   };
 
    ICont &non_const_icont() const
    {  return const_cast(this->members_.m_icont);   }
@@ -490,12 +475,14 @@ struct node_alloc_holder
 
    const NodeAlloc &node_alloc() const
    {  return static_cast(this->members_);   }
+
+   members_holder members_;
 };
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 }  //namespace container {
 }  //namespace boost {
 
 #include 
 
-#endif // BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
+#endif // BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
diff --git a/include/boost/container/detail/node_pool_impl.hpp b/include/boost/container/detail/node_pool_impl.hpp
index 56bd144..9ee9e31 100644
--- a/include/boost/container/detail/node_pool_impl.hpp
+++ b/include/boost/container/detail/node_pool_impl.hpp
@@ -19,7 +19,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -32,7 +32,7 @@
 
 namespace boost {
 namespace container {
-namespace containers_detail {
+namespace container_detail {
 
 template
 class private_node_pool_impl
@@ -82,7 +82,7 @@ class private_node_pool_impl
 
    //!Returns the segment manager. Never throws
    segment_manager_base_type* get_segment_manager_base()const
-   {  return containers_detail::get_pointer(mp_segment_mngr_base);  }
+   {  return container_detail::to_raw_pointer(mp_segment_mngr_base);  }
 
    void *allocate_node()
    {  return priv_alloc_node();  }
@@ -346,8 +346,8 @@ class private_node_pool_impl
    }
 
    private:
-   typedef typename boost::pointer_to_other
-      ::type   segment_mngr_base_ptr_t;
+   typedef typename boost::intrusive::pointer_traits
+      ::template rebind_pointer::type   segment_mngr_base_ptr_t;
 
    const size_type m_nodes_per_block;
    const size_type m_real_node_size;
@@ -358,7 +358,7 @@ class private_node_pool_impl
 };
 
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 }  //namespace container {
 }  //namespace boost {
 
diff --git a/include/boost/container/detail/pair.hpp b/include/boost/container/detail/pair.hpp
index fd98a72..1aeff91 100644
--- a/include/boost/container/detail/pair.hpp
+++ b/include/boost/container/detail/pair.hpp
@@ -10,8 +10,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_CONTAINERS_DETAIL_PAIR_HPP
-#define BOOST_CONTAINERS_CONTAINERS_DETAIL_PAIR_HPP
+#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
+#define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -28,13 +28,13 @@
 #include 
 #include 
 
-#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
+#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
 #include 
 #endif
 
 namespace boost {
 namespace container { 
-namespace containers_detail {
+namespace container_detail {
 
 template 
 struct pair;
@@ -143,13 +143,13 @@ struct pair
 /*
    //Variadic versions
    template
-   pair(BOOST_CONTAINERS_PARAM(U, u), typename containers_detail::disable_if
-         < containers_detail::is_pair< typename containers_detail::remove_ref_const::type >, pair_nat>::type* = 0)
+   pair(BOOST_CONTAINER_PP_PARAM(U, u), typename container_detail::disable_if
+         < container_detail::is_pair< typename container_detail::remove_ref_const::type >, pair_nat>::type* = 0)
       : first(::boost::forward(u))
       , second()
    {}
 
-   #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    template
    pair(U &&u, V &&v)
@@ -161,13 +161,13 @@ struct pair
 
    #define BOOST_PP_LOCAL_MACRO(n)                                                            \
    template                                        \
-   pair(BOOST_CONTAINERS_PARAM(U, u)                                                          \
-       ,BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                                  \
+   pair(BOOST_CONTAINER_PP_PARAM(U, u)                                                          \
+       ,BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                                  \
       : first(::boost::forward(u))                             \
-      , second(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))                        \
+      , second(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))                        \
    {}                                                                                         \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
    #endif
 */
@@ -280,7 +280,7 @@ inline void swap(pair& x, pair& y)
    swap(x.second, y.second);
 }
 
-}  //namespace containers_detail { 
+}  //namespace container_detail { 
 }  //namespace container { 
 
 
@@ -291,7 +291,7 @@ template
 struct is_enum;
 
 template
-struct is_enum< ::boost::container::containers_detail::pair >
+struct is_enum< ::boost::container::container_detail::pair >
 {
    static const bool value = false;
 };
@@ -299,14 +299,14 @@ struct is_enum< ::boost::container::containers_detail::pair >
 //This specialization is needed to avoid instantiation of pair in
 //is_class, and allow recursive maps.
 template 
-struct is_class< ::boost::container::containers_detail::pair >
+struct is_class< ::boost::container::container_detail::pair >
    : public ::boost::true_type
 {};
 
 #ifdef BOOST_NO_RVALUE_REFERENCES
 
 template
-struct has_move_emulation_enabled< ::boost::container::containers_detail::pair >
+struct has_move_emulation_enabled< ::boost::container::container_detail::pair >
    : ::boost::true_type
 {};
 
@@ -317,4 +317,4 @@ struct has_move_emulation_enabled< ::boost::container::containers_detail::pair
 
-#endif   //#ifndef BOOST_CONTAINERS_DETAIL_PAIR_HPP
+#endif   //#ifndef BOOST_CONTAINER_DETAIL_PAIR_HPP
diff --git a/include/boost/container/detail/pool_common.hpp b/include/boost/container/detail/pool_common.hpp
index c647710..c66e2cd 100644
--- a/include/boost/container/detail/pool_common.hpp
+++ b/include/boost/container/detail/pool_common.hpp
@@ -21,7 +21,7 @@
 
 namespace boost {
 namespace container {
-namespace containers_detail {
+namespace container_detail {
 
 template
 struct node_slist
@@ -43,7 +43,7 @@ struct is_stateless_segment_manager
    static const bool value = false;
 };
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 }  //namespace container {
 }  //namespace boost {
 
diff --git a/include/boost/container/detail/preprocessor.hpp b/include/boost/container/detail/preprocessor.hpp
index 72a5904..9916fba 100644
--- a/include/boost/container/detail/preprocessor.hpp
+++ b/include/boost/container/detail/preprocessor.hpp
@@ -8,32 +8,43 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP
-#define BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP
+#ifndef BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
+#define BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
 #endif
 
-#include "config_begin.hpp"
+#include 
 
 #ifndef BOOST_NO_RVALUE_REFERENCES
 #include 
-#endif
+#endif   //#ifndef BOOST_NO_RVALUE_REFERENCES
 
 #include 
 
-#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
-#error "This file is not needed when perfect forwarding is available"
-#endif
+#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+//#error "This file is not needed when perfect forwarding is available"
+#endif   //BOOST_CONTAINER_PERFECT_FORWARDING
 
 #include  
-#include 
+#include 
+#include 
+#include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
-#define BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS 10
+#define BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS 10
 
 //Note:
 //We define template parameters as const references to
@@ -42,100 +53,126 @@
 //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
-   #define BOOST_CONTAINERS_PP_PARAM_LIST(z, n, data) \
+   #define BOOST_CONTAINER_PP_PARAM_LIST(z, n, data) \
    BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
    //!
 #else
-   #define BOOST_CONTAINERS_PP_PARAM_LIST(z, n, data) \
+   #define BOOST_CONTAINER_PP_PARAM_LIST(z, n, data) \
    const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
    //!
-#endif
+#endif   //#ifndef BOOST_NO_RVALUE_REFERENCES
 
 #ifndef BOOST_NO_RVALUE_REFERENCES
-   #define BOOST_CONTAINERS_PARAM(U, u) \
+   #define BOOST_CONTAINER_PP_PARAM(U, u) \
    U && u \
    //!
 #else
-   #define BOOST_CONTAINERS_PARAM(U, u) \
+   #define BOOST_CONTAINER_PP_PARAM(U, u) \
    const U & u \
    //!
-#endif
+#endif   //#ifndef BOOST_NO_RVALUE_REFERENCES
 
 #ifndef BOOST_NO_RVALUE_REFERENCES
 
-#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+   #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
 
-#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \
-  BOOST_PP_CAT(m_p, n) (boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ))           \
-//!
+      #define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
+      BOOST_PP_CAT(m_p, n) (boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ))           \
+      //!
 
-#else
+   #else    //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
 
-#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \
-  BOOST_PP_CAT(m_p, n) (static_cast( BOOST_PP_CAT(p, n) ))           \
-//!
+      #define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
+      BOOST_PP_CAT(m_p, n) (static_cast( BOOST_PP_CAT(p, n) ))           \
+      //!
 
-#endif
+   #endif   //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
 
-#else
-#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \
-  BOOST_PP_CAT(m_p, n) (const_cast(BOOST_PP_CAT(p, n))) \
-//!
-#endif
+#else //BOOST_NO_RVALUE_REFERENCES
 
-#define BOOST_CONTAINERS_AUX_PARAM_INC(z, n, data)   \
-  BOOST_PP_CAT(++m_p, n)                        \
-//!
+   #define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
+   BOOST_PP_CAT(m_p, n) (const_cast(BOOST_PP_CAT(p, n))) \
+   //!
+#endif   //#ifndef BOOST_NO_RVALUE_REFERENCES
 
 #ifndef BOOST_NO_RVALUE_REFERENCES
 
-#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+   #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
 
-#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data)  \
-  BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n);            \
-//!
+      #define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data)  \
+      BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n);            \
+      //!
 
-#else
+   #else //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
 
-#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data)  \
-  BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n);            \
-//!
+      #define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data)  \
+      BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n);            \
+      //!
 
-#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+   #endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
 
+#else //BOOST_NO_RVALUE_REFERENCES
 
-#else
-#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data)  \
-  BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n);             \
-//!
-#endif
-
-#define BOOST_CONTAINERS_PP_PARAM_FORWARD(z, n, data) \
-boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
-//!
+   #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
 
 #if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
 
-#define BOOST_CONTAINERS_PP_MEMBER_FORWARD(z, n, data) \
-::boost::container::containers_detail::stored_ref< BOOST_PP_CAT(P, n) >::forward( BOOST_PP_CAT(m_p, n) ) \
-//!
+   #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) ) \
+   //!
 
-#else
+#else //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
 
-#define BOOST_CONTAINERS_PP_MEMBER_FORWARD(z, n, data) \
-boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
-//!
+   #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)
 
-#define BOOST_CONTAINERS_PP_MEMBER_IT_FORWARD(z, n, data) \
-BOOST_PP_CAT(*m_p, n) \
+#define BOOST_CONTAINER_PP_PARAM_INC(z, n, data)   \
+  BOOST_PP_CAT(++this->m_p, n)                     \
+//!
+
+#define BOOST_CONTAINER_PP_IDENTITY(z, n, data) data
+
+
+#define BOOST_CONTAINER_PP_PARAM_FORWARD(z, n, data) \
+boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
+//!
+
+#define BOOST_CONTAINER_PP_DECLVAL(z, n, data) \
+boost::move_detail::declval< BOOST_PP_CAT(P, n) >() \
+//!
+
+#define BOOST_CONTAINER_PP_MEMBER_IT_FORWARD(z, n, data) \
+BOOST_PP_CAT(*this->m_p, n) \
+//!
+
+#define BOOST_CONTAINER_PP_TEMPLATE_PARAM_VOID_DEFAULT(z, n, data)   \
+  BOOST_PP_CAT(class P, n) = void                                      \
+//!
+
+#define BOOST_CONTAINER_PP_STATIC_PARAM_REF_DECLARE(z, n, data) \
+   static BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n); \
+//!
+
+#define BOOST_CONTAINER_PP_PARAM_PASS(z, n, data) \
+   BOOST_PP_CAT(p, n) \
+//!
+
+#define BOOST_CONTAINER_PP_FWD_TYPE(z, n, data) \
+   typename ::boost::move_detail::forward_type< BOOST_PP_CAT(P, n) >::type \
 //!
 
 #include 
 
-#else
-#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
-#error "This file is not needed when perfect forwarding is available"
-#endif
-#endif //#ifndef BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP
+//#else
+
+//#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+//#error "This file is not needed when perfect forwarding is available"
+//#endif   //BOOST_CONTAINER_PERFECT_FORWARDING
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
diff --git a/include/boost/container/detail/stored_ref.hpp b/include/boost/container/detail/stored_ref.hpp
index 8270e14..df0faa8 100644
--- a/include/boost/container/detail/stored_ref.hpp
+++ b/include/boost/container/detail/stored_ref.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_STORED_REF_HPP
-#define BOOST_CONTAINERS_DETAIL_STORED_REF_HPP
+#ifndef BOOST_CONTAINER_DETAIL_STORED_REF_HPP
+#define BOOST_CONTAINER_DETAIL_STORED_REF_HPP
 
 #include "config_begin.hpp"
 #include 
@@ -18,7 +18,7 @@
 
 namespace boost{
 namespace container{
-namespace containers_detail{
+namespace container_detail{
 
 template
 struct stored_ref
@@ -79,7 +79,7 @@ struct stored_ref
    {  return t; }
 };
 
-}  //namespace containers_detail{
+}  //namespace container_detail{
 }  //namespace container{
 }  //namespace boost{
 
@@ -89,4 +89,4 @@ struct stored_ref
 
 #include 
 
-#endif   //BOOST_CONTAINERS_DETAIL_STORED_REF_HPP
+#endif   //BOOST_CONTAINER_DETAIL_STORED_REF_HPP
diff --git a/include/boost/container/detail/transform_iterator.hpp b/include/boost/container/detail/transform_iterator.hpp
index b6176fb..17eca9e 100644
--- a/include/boost/container/detail/transform_iterator.hpp
+++ b/include/boost/container/detail/transform_iterator.hpp
@@ -11,8 +11,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP
-#define BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP
+#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
+#define BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -59,7 +59,7 @@ class transform_iterator
    : public UnaryFunction
    , public std::iterator
       < typename Iterator::iterator_category
-      , typename containers_detail::remove_reference::type
+      , typename container_detail::remove_reference::type
       , typename Iterator::difference_type
       , operator_arrow_proxy
       , typename UnaryFunction::result_type>
@@ -173,4 +173,4 @@ make_transform_iterator(Iterator it, UnaryFunc fun)
 
 #include 
 
-#endif   //#ifndef BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP
+#endif   //#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp
index 012fb2d..2a60e11 100644
--- a/include/boost/container/detail/tree.hpp
+++ b/include/boost/container/detail/tree.hpp
@@ -8,15 +8,15 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_TREE_HPP
-#define BOOST_CONTAINERS_TREE_HPP
+#ifndef BOOST_CONTAINER_TREE_HPP
+#define BOOST_CONTAINER_TREE_HPP
 
 #include "config_begin.hpp"
 #include 
 #include 
 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -27,7 +27,8 @@
 #include 
 #include 
 #include 
-#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
+#include 
+#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
 #include 
 #endif
 
@@ -37,7 +38,7 @@
 
 namespace boost {
 namespace container {
-namespace containers_detail {
+namespace container_detail {
 
 template
 struct value_compare_impl
@@ -82,10 +83,10 @@ struct value_compare_impl
 template
 struct rbtree_hook
 {
-   typedef typename containers_detail::bi::make_set_base_hook
-      < containers_detail::bi::void_pointer
-      , containers_detail::bi::link_mode
-      , containers_detail::bi::optimize_size
+   typedef typename container_detail::bi::make_set_base_hook
+      < container_detail::bi::void_pointer
+      , container_detail::bi::link_mode
+      , container_detail::bi::optimize_size
       >::type  type;
 };
 
@@ -105,6 +106,10 @@ template 
 struct rbtree_node
    :  public rbtree_hook::type
 {
+   private:
+   BOOST_COPYABLE_AND_MOVABLE(rbtree_node)
+
+   public:
    typedef typename rbtree_hook::type hook_type;
 
    typedef T value_type;
@@ -112,8 +117,6 @@ struct rbtree_node
 
    typedef rbtree_node node_type;
 
-   #ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
-
    rbtree_node()
       : m_data()
    {}
@@ -122,30 +125,35 @@ struct rbtree_node
       : m_data(other.m_data)
    {}
 
-   #define BOOST_PP_LOCAL_MACRO(n)                                                           \
-   template                                                \
-   rbtree_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                        \
-      : m_data(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))                     \
-   {}                                                                                        \
+   rbtree_node(BOOST_RV_REF(rbtree_node) other)
+      : m_data(boost::move(other.m_data))
+   {}
+
+   #ifndef BOOST_CONTAINER_PERFECT_FORWARDING
+
+   #define BOOST_PP_LOCAL_MACRO(n)                                           \
+   template                                \
+   rbtree_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))           \
+      : m_data(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))        \
+   {}                                                                        \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #else //#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
-
-   rbtree_node()
-      : m_data()
-   {}
+   #else //#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
 
    template
    rbtree_node(Args &&...args)
       : m_data(boost::forward(args)...)
    {}
-   #endif//#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif//#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
 
    rbtree_node &operator=(const rbtree_node &other)
    {  do_assign(other.m_data);   return *this;  }
 
+   rbtree_node &operator=(BOOST_RV_REF(rbtree_node) other)
+   {  do_move(other.m_data);   return *this;  }
+
    T &get_data()
    {
       T* ptr = reinterpret_cast(&this->m_data);
@@ -179,76 +187,88 @@ struct rbtree_node
    void do_assign(const V &v)
    {  m_data = v; }
 
-   public:
-   template
-   static void construct(node_type *ptr, BOOST_FWD_REF(Convertible) convertible)
-   {  new(ptr) node_type(boost::forward(convertible));  }
+   template
+   void do_move(std::pair &p)
+   {
+      const_cast(m_data.first) = boost::move(p.first);
+      m_data.second  = boost::move(p.second);
+   }
+
+   template
+   void do_move(pair &p)
+   {
+      const_cast(m_data.first) = boost::move(p.first);
+      m_data.second  = boost::move(p.second);
+   }
+
+   template
+   void do_move(V &v)
+   {  m_data = boost::move(v); }
 };
 
-}//namespace containers_detail {
-#if defined(BOOST_NO_RVALUE_REFERENCES)
-template
-struct has_own_construct_from_it
-   < boost::container::containers_detail::rbtree_node >
-{
-   static const bool value = true;
-};
-#endif
-namespace containers_detail {
+}//namespace container_detail {
+
+namespace container_detail {
 
 template
 struct intrusive_rbtree_type
 {
-   typedef typename A::value_type                  value_type;
-   typedef typename boost::pointer_to_other
-      ::type            void_pointer;
-   typedef typename containers_detail::rbtree_node
+   typedef typename boost::container::
+      allocator_traits::value_type              value_type;
+   typedef typename boost::container::
+      allocator_traits::void_pointer            void_pointer;
+   typedef typename boost::container::
+      allocator_traits::size_type               size_type;
+   typedef typename container_detail::rbtree_node
                          node_type;
    typedef node_compare   node_compare_type;
-   typedef typename containers_detail::bi::make_rbtree
+   typedef typename container_detail::bi::make_rbtree
       
-      ,containers_detail::bi::base_hook::type>
-      ,containers_detail::bi::constant_time_size
-      ,containers_detail::bi::size_type
+      ,container_detail::bi::compare
+      ,container_detail::bi::base_hook::type>
+      ,container_detail::bi::constant_time_size
+      ,container_detail::bi::size_type
       >::type                                      container_type;
    typedef container_type                          type ;
 };
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 
-namespace containers_detail {
+namespace container_detail {
 
 template 
 class rbtree
-   : protected containers_detail::node_alloc_holder
-        
          >::type
+      , KeyCompare
       >
 {
-   typedef typename containers_detail::intrusive_rbtree_type
-         
-         >::type                                      Icont;
-   typedef containers_detail::node_alloc_holder        AllocHolder;
-   typedef typename AllocHolder::NodePtr              NodePtr;
+         >::type                                            Icont;
+   typedef container_detail::node_alloc_holder  
+                                      AllocHolder;
+   typedef typename AllocHolder::NodePtr                    NodePtr;
    typedef rbtree < Key, Value, KeyOfValue
-                  , KeyCompare, A>                    ThisType;
-   typedef typename AllocHolder::NodeAlloc            NodeAlloc;
-   typedef typename AllocHolder::ValAlloc             ValAlloc;
-   typedef typename AllocHolder::Node                 Node;
-   typedef typename Icont::iterator                   iiterator;
-   typedef typename Icont::const_iterator             iconst_iterator;
-   typedef containers_detail::allocator_destroyer     Destroyer;
-   typedef typename AllocHolder::allocator_v1         allocator_v1;
-   typedef typename AllocHolder::allocator_v2         allocator_v2;
-   typedef typename AllocHolder::alloc_version        alloc_version;
+                  , KeyCompare, A>                          ThisType;
+   typedef typename AllocHolder::NodeAlloc                  NodeAlloc;
+   typedef typename AllocHolder::ValAlloc                   ValAlloc;
+   typedef typename AllocHolder::Node                       Node;
+   typedef typename Icont::iterator                         iiterator;
+   typedef typename Icont::const_iterator                   iconst_iterator;
+   typedef container_detail::allocator_destroyer Destroyer;
+   typedef typename AllocHolder::allocator_v1               allocator_v1;
+   typedef typename AllocHolder::allocator_v2               allocator_v2;
+   typedef typename AllocHolder::alloc_version              alloc_version;
 
    class RecyclingCloner;
    friend class RecyclingCloner;
-   
+
    class RecyclingCloner
    {
       public:
@@ -258,10 +278,8 @@ class rbtree
 
       NodePtr operator()(const Node &other) const
       {
-//         if(!m_icont.empty()){
          if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
             //First recycle a node (this can't throw)
-            //NodePtr p = m_icont.unlink_leftmost_without_rebalance();
             try{
                //This can throw
                *p = other;
@@ -284,6 +302,44 @@ class rbtree
       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 = boost::move(other);
+               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);
+         }
+      }
+
+      AllocHolder &m_holder;
+      Icont &m_icont;
+   };
+
    BOOST_COPYABLE_AND_MOVABLE(rbtree)
 
    public:
@@ -294,12 +350,18 @@ class rbtree
    typedef KeyCompare                                 key_compare;
    typedef value_compare_impl< Key, Value
                         , KeyCompare, KeyOfValue>     value_compare;
-   typedef typename A::pointer                        pointer;
-   typedef typename A::const_pointer                  const_pointer;
-   typedef typename A::reference                      reference;
-   typedef typename A::const_reference                const_reference;
-   typedef typename A::size_type                      size_type;
-   typedef typename A::difference_type                difference_type;
+   typedef typename boost::container::
+      allocator_traits::pointer                    pointer;
+   typedef typename boost::container::
+      allocator_traits::const_pointer              const_pointer;
+   typedef typename boost::container::
+      allocator_traits::reference                  reference;
+   typedef typename boost::container::
+      allocator_traits::const_reference            const_reference;
+   typedef typename boost::container::
+      allocator_traits::size_type                  size_type;
+   typedef typename boost::container::
+      allocator_traits::difference_type            difference_type;
    typedef difference_type                            rbtree_difference_type;
    typedef pointer                                    rbtree_pointer;
    typedef const_pointer                              rbtree_const_pointer;
@@ -436,8 +498,11 @@ class rbtree
    typedef std::reverse_iterator        reverse_iterator;
    typedef std::reverse_iterator  const_reverse_iterator;
 
-   rbtree(const key_compare& comp = key_compare(), 
-           const allocator_type& a = allocator_type())
+   rbtree()
+      : AllocHolder(key_compare())
+   {}
+
+   rbtree(const key_compare& comp, const allocator_type& a = allocator_type())
       : AllocHolder(a, comp)
    {}
 
@@ -467,26 +532,32 @@ class rbtree
    }
 
    rbtree(BOOST_RV_REF(rbtree) x) 
-      :  AllocHolder(x, x.key_comp())
-   {  this->swap(x);  }
+      :  AllocHolder(boost::move(static_cast(x)), x.key_comp())
+   {}
 
    ~rbtree()
    {} //AllocHolder clears the tree
 
    rbtree& operator=(BOOST_COPY_ASSIGN_REF(rbtree) x)
    {
-      if (this != &x) {
+      if (&x != this){
+         NodeAlloc &this_alloc     = this->get_stored_allocator();
+         const NodeAlloc &x_alloc  = x.get_stored_allocator();
+         container_detail::bool_::
+            propagate_on_container_copy_assignment::value> flag;
+         if(flag && this_alloc != x_alloc){
+            this->clear();
+         }
+         this->AllocHolder::copy_assign_alloc(x);
          //Transfer all the nodes to a temporary tree
          //If anything goes wrong, all the nodes will be destroyed
          //automatically
-         Icont other_tree(this->icont().value_comp());
-         other_tree.swap(this->icont());
+         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(*this, other_tree)
-            //, AllocHolder::cloner(*this)
             , Destroyer(this->node_alloc()));
 
          //If there are remaining nodes, destroy them
@@ -498,8 +569,41 @@ class rbtree
       return *this;
    }
 
-   rbtree& operator=(BOOST_RV_REF(rbtree) mx)
-   {  this->clear(); this->swap(mx);   return *this;  }
+   rbtree& operator=(BOOST_RV_REF(rbtree) 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);
+            }
+         }
+      }
+      return *this;
+   }
 
    public:    
    // accessors:
@@ -677,7 +781,7 @@ class rbtree
 
    public:
 
-   #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    template 
    iterator emplace_unique(Args&&... args)
@@ -701,59 +805,43 @@ class rbtree
       return iterator(this->icont().insert_equal(hint.get(), *p));
    }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
-
-   iterator emplace_unique()
-   {  return this->emplace_unique_impl(AllocHolder::create_node());   }
-
-   iterator emplace_hint_unique(const_iterator hint)
-   {  return this->emplace_unique_hint_impl(hint, AllocHolder::create_node());   }
-
-   iterator emplace_equal()
-   {
-      NodePtr p(AllocHolder::create_node());
-      return iterator(this->icont().insert_equal(this->icont().end(), *p));
-   }
-
-   iterator emplace_hint_equal(const_iterator hint)
-   {
-      NodePtr p(AllocHolder::create_node());
-      return iterator(this->icont().insert_equal(hint.get(), *p));
-   }
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    #define BOOST_PP_LOCAL_MACRO(n)                                                                          \
-   template                                                               \
-   iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                           \
+   BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >)                   \
+   iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                             \
    {                                                                                                        \
       return this->emplace_unique_impl                                                                      \
-         (AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)));              \
+         (AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)));                \
    }                                                                                                        \
                                                                                                             \
-   template                                                               \
-   iterator emplace_hint_unique(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
+   BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >)                   \
+   iterator emplace_hint_unique(const_iterator hint                                                         \
+                       BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                        \
    {                                                                                                        \
       return this->emplace_unique_hint_impl                                                                 \
-         (hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)));        \
+         (hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)));          \
    }                                                                                                        \
                                                                                                             \
-   template                                                               \
-   iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                            \
+   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_CONTAINERS_PP_PARAM_FORWARD, _)));        \
+      NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)));          \
       return iterator(this->icont().insert_equal(this->icont().end(), *p));                                 \
    }                                                                                                        \
                                                                                                             \
-   template                                                               \
-   iterator emplace_hint_equal(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))  \
+   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_CONTAINERS_PP_PARAM_FORWARD, _)));        \
+      NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)));          \
       return iterator(this->icont().insert_equal(hint.get(), *p));                                          \
    }                                                                                                        \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    iterator insert_unique(const_iterator hint, const value_type& v)
    {
@@ -1044,7 +1132,7 @@ swap(rbtree& x,
   x.swap(y);
 }
 
-} //namespace containers_detail {
+} //namespace container_detail {
 } //namespace container {
 /*
 //!has_trivial_destructor_after_move<> == true_type
@@ -1052,7 +1140,7 @@ swap(rbtree& x,
 template 
 struct has_trivial_destructor_after_move
-    >
+    >
 {
    static const bool value = has_trivial_destructor::value && has_trivial_destructor::value;
 };
@@ -1061,4 +1149,4 @@ struct has_trivial_destructor_after_move
 
 #include 
 
-#endif //BOOST_CONTAINERS_TREE_HPP
+#endif //BOOST_CONTAINER_TREE_HPP
diff --git a/include/boost/container/detail/type_traits.hpp b/include/boost/container/detail/type_traits.hpp
index 28095ba..6a0b3ed 100644
--- a/include/boost/container/detail/type_traits.hpp
+++ b/include/boost/container/detail/type_traits.hpp
@@ -12,8 +12,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
-#define BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
+#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
+#define BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -25,7 +25,7 @@
 
 namespace boost {
 namespace container { 
-namespace containers_detail {
+namespace container_detail {
 
 struct nat{};
 
@@ -194,10 +194,10 @@ struct remove_ref_const
    typedef typename remove_const< typename remove_reference::type >::type type;
 };
 
-} // namespace containers_detail
+} // namespace container_detail
 }  //namespace container { 
 }  //namespace boost {
 
 #include 
 
-#endif   //#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
+#endif   //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
diff --git a/include/boost/container/detail/utilities.hpp b/include/boost/container/detail/utilities.hpp
index 78e9ccd..ee0fe99 100644
--- a/include/boost/container/detail/utilities.hpp
+++ b/include/boost/container/detail/utilities.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_UTILITIES_HPP
-#define BOOST_CONTAINERS_DETAIL_UTILITIES_HPP
+#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
+#define BOOST_CONTAINER_DETAIL_UTILITIES_HPP
 
 #include "config_begin.hpp"
 #include 
@@ -21,11 +21,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 namespace boost {
 namespace container {
-namespace containers_detail {
+namespace container_detail {
 
 template
 const T &max_value(const T &a, const T &b)
@@ -55,29 +56,14 @@ SizeType
    return max_size;
 }
 
-template
-struct smart_ptr_type
-{
-   typedef typename SmartPtr::value_type value_type;
-   typedef value_type *pointer;
-   static pointer get (const SmartPtr &smartptr)
-   {  return smartptr.get();}
-};
+template 
+inline T* to_raw_pointer(T* p)
+{  return p; }
 
-template
-struct smart_ptr_type
-{
-   typedef T value_type;
-   typedef value_type *pointer;
-   static pointer get (pointer ptr)
-   {  return ptr;}
-};
-
-//!Overload for smart pointers to avoid ADL problems with get_pointer
-template
-inline typename smart_ptr_type::pointer
-get_pointer(const Ptr &ptr)
-{  return smart_ptr_type::get(ptr);   }
+template 
+inline typename 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 
@@ -87,6 +73,33 @@ inline void do_swap(T& x, T& y)
    swap(x, y);
 }
 
+template
+inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false_type)
+   BOOST_CONTAINER_NOEXCEPT
+{}
+
+template
+inline void swap_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type)
+{  container_detail::do_swap(l, r);   }
+
+template
+inline void assign_alloc(AllocatorType &, const AllocatorType &, container_detail::false_type)
+   BOOST_CONTAINER_NOEXCEPT
+{}
+
+template
+inline void assign_alloc(AllocatorType &l, const AllocatorType &r, container_detail::true_type)
+{  l = r;   }
+
+template
+inline void move_alloc(AllocatorType &, AllocatorType &, container_detail::false_type)
+   BOOST_CONTAINER_NOEXCEPT
+{}
+
+template
+inline void move_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type)
+{  l = ::boost::move(r);   }
+
 //Rounds "orig_size" by excess to round_to bytes
 template
 inline SizeType get_rounded_size(SizeType orig_size, SizeType round_to)
@@ -99,36 +112,36 @@ struct ct_rounded_size
 {
    enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
 };
-
+/*
 template 
 struct __rw_is_enum
 {
-struct _C_no { };
-struct _C_yes { int _C_dummy [2]; };
+   struct _C_no { };
+   struct _C_yes { int _C_dummy [2]; };
 
-struct _C_indirect {
-// prevent classes with user-defined conversions from matching
+   struct _C_indirect {
+   // prevent classes with user-defined conversions from matching
 
-// use double to prevent float->int gcc conversion warnings
-_C_indirect (double);
+   // use double to prevent float->int gcc conversion warnings
+   _C_indirect (double);
 };
 
 // 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);
+   // supply first argument to prevent HP aCC warnings
+   static _C_no _C_is (int, ...);
+   static _C_yes _C_is (int, _C_indirect);
 
-static _TypeT _C_make_T ();
+   static _TypeT _C_make_T ();
 };
 
 enum {
-_C_val = sizeof (_C_yes)
-== sizeof (_C_nest::_C_is (0, _C_nest::_C_make_T ()))
-&& !::boost::is_fundamental<_TypeT>::value
+   _C_val = sizeof (_C_yes) == sizeof (_C_nest::_C_is (0, _C_nest::_C_make_T ()))
+   && !::boost::is_fundamental<_TypeT>::value
 };
 
 }; 
+*/
 
 template
 struct move_const_ref_type
@@ -140,11 +153,119 @@ struct move_const_ref_type
    >
 {};
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//                               uninitialized_move_alloc
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! Effects:
+//!   \code
+//!   for (; first != last; ++result, ++first)
+//!      allocator_traits::construct(a, &*result, boost::move(*first));
+//!   \endcode
+//!
+//! Returns: result
+template
+    // F models ForwardIterator
+F uninitialized_move_alloc(A &a, I f, I l, F r)
+{
+   while (f != l) {
+      allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f));
+      ++f; ++r;
+   }
+   return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//                               uninitialized_copy_alloc
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! Effects:
+//!   \code
+//!   for (; first != last; ++result, ++first)
+//!      allocator_traits::construct(a, &*result, *first);
+//!   \endcode
+//!
+//! Returns: result
+template
+    // F models ForwardIterator
+F uninitialized_copy_alloc(A &a, I f, I l, F r)
+{
+   while (f != l) {
+      allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), *f);
+      ++f; ++r;
+   }
+   return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//                               uninitialized_copy_alloc
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! Effects:
+//!   \code
+//!   for (; first != last; ++result, ++first)
+//!      allocator_traits::construct(a, &*result, *first);
+//!   \endcode
+//!
+//! Returns: result
+template
+    
+void uninitialized_fill_alloc(A &a, F f, F l, const T &t)
+{
+   while (f != l) {
+      allocator_traits::construct(a, container_detail::to_raw_pointer(&*f), t);
+      ++f;
+   }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//                            uninitialized_copy_or_move_alloc
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+   // 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 >::type* = 0)
+{
+   return ::boost::container::uninitialized_move_alloc(a, f, l, r);
+}
+
+template
+   // 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 >::type* = 0)
+{
+   return ::boost::container::uninitialized_copy_alloc(a, f, l, r);
+}
+
 }  //namespace container {
 }  //namespace boost {
 
 
 #include 
 
-#endif   //#ifndef BOOST_CONTAINERS_DETAIL_UTILITIES_HPP
+#endif   //#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
diff --git a/include/boost/container/detail/value_init.hpp b/include/boost/container/detail/value_init.hpp
index 5145fe9..afbc9c1 100644
--- a/include/boost/container/detail/value_init.hpp
+++ b/include/boost/container/detail/value_init.hpp
@@ -10,8 +10,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP
-#define BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP
+#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
+#define BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -22,7 +22,7 @@
 
 namespace boost {
 namespace container { 
-namespace containers_detail {
+namespace container_detail {
 
 template
 struct value_init
@@ -31,13 +31,15 @@ struct value_init
       : m_t()
    {}
 
+   operator T &() { return m_t; }
+
    T m_t;
 };
 
-}  //namespace containers_detail { 
+}  //namespace container_detail { 
 }  //namespace container { 
 }  //namespace boost {
 
 #include 
 
-#endif   //#ifndef BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP
+#endif   //#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
diff --git a/include/boost/container/detail/variadic_templates_tools.hpp b/include/boost/container/detail/variadic_templates_tools.hpp
index c16992e..f21f972 100644
--- a/include/boost/container/detail/variadic_templates_tools.hpp
+++ b/include/boost/container/detail/variadic_templates_tools.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
-#define BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
+#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
+#define BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -22,7 +22,7 @@
 
 namespace boost {
 namespace container { 
-namespace containers_detail {
+namespace container_detail {
 
 template
 class tuple;
@@ -146,8 +146,8 @@ struct build_number_seq<0, index_tuple >
 {  typedef index_tuple type;  };
 
 
-}}}   //namespace boost { namespace container { namespace containers_detail {
+}}}   //namespace boost { namespace container { namespace container_detail {
 
 #include 
 
-#endif   //#ifndef BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
+#endif   //#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
diff --git a/include/boost/container/detail/version_type.hpp b/include/boost/container/detail/version_type.hpp
index a194342..46344fa 100644
--- a/include/boost/container/detail/version_type.hpp
+++ b/include/boost/container/detail/version_type.hpp
@@ -13,8 +13,8 @@
 //////////////////////////////////////////////////////////////////////////////
 
 
-#ifndef BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP
-#define BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP
+#ifndef BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
+#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
 
 #include "config_begin.hpp"
 
@@ -23,13 +23,13 @@
 
 namespace boost{
 namespace container {
-namespace containers_detail {
+namespace container_detail {
 
 //using namespace boost;
 
 template 
 struct version_type
-    : public containers_detail::integral_constant
+    : public container_detail::integral_constant
 {
     typedef T type;
 
@@ -39,7 +39,7 @@ struct version_type
 namespace impl{
 
 template , typename T::version>::value>
+          bool = container_detail::is_convertible, typename T::version>::value>
 struct extract_version
 {
    static const unsigned value = 1;
@@ -79,14 +79,14 @@ struct version
 
 template 
 struct version
-   : public containers_detail::integral_constant::value>
+   : public container_detail::integral_constant::value>
 {
 };
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 }  //namespace container {
 }  //namespace boost{
 
 #include "config_end.hpp"
 
-#endif   //#define BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP
+#endif   //#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp
index 2846590..45ab2f2 100644
--- a/include/boost/container/detail/workaround.hpp
+++ b/include/boost/container/detail/workaround.hpp
@@ -8,17 +8,24 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP
-#define BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP
+#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
+#define BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
 
-#include "config_begin.hpp"
+#include 
 
 #if    !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)\
     && !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
-#define BOOST_CONTAINERS_PERFECT_FORWARDING
+   #define BOOST_CONTAINER_PERFECT_FORWARDING
+#endif
 
+#if defined(BOOST_NO_NOEXCEPT)
+   #define BOOST_CONTAINER_NOEXCEPT
+   #define BOOST_CONTAINER_NOEXCEPT_IF(x)
+#else
+   #define BOOST_CONTAINER_NOEXCEPT    noexcept
+   #define BOOST_CONTAINER_NOEXCEPT_IF(x) noexcept(x)
 #endif
 
 #include 
 
-#endif   //#ifndef BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP
+#endif   //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp
index c637ef5..bb35ce2 100644
--- a/include/boost/container/flat_map.hpp
+++ b/include/boost/container/flat_map.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_FLAT_MAP_HPP
-#define BOOST_CONTAINERS_FLAT_MAP_HPP
+#ifndef BOOST_CONTAINER_FLAT_MAP_HPP
+#define BOOST_CONTAINER_FLAT_MAP_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -52,6 +53,23 @@ inline bool operator==(const flat_map& x,
 template 
 inline bool operator<(const flat_map& x, 
                       const flat_map& y);
+
+namespace container_detail{
+
+template
+static D &force(const S &s)
+{  return *const_cast((reinterpret_cast(&s))); }
+
+template
+static D force_copy(S s)
+{
+   D *vp = reinterpret_cast(&s);
+   return D(*vp);
+}
+
+}  //namespace container_detail{
+
+
 /// @endcond
 
 //! A flat_map is a kind of associative container that supports unique keys (contains at
@@ -86,19 +104,19 @@ class flat_map
    private:
    BOOST_COPYABLE_AND_MOVABLE(flat_map)
    //This is the tree that we should store if pair was movable
-   typedef containers_detail::flat_tree, 
-                           containers_detail::select1st< std::pair >, 
+                           container_detail::select1st< std::pair >, 
                            Pred, 
                            A> tree_t;
 
    //This is the real tree stored here. It's based on a movable pair
-   typedef containers_detail::flat_tree, 
-                           containers_detail::select1st >, 
+   typedef container_detail::flat_tree, 
+                           container_detail::select1st >, 
                            Pred, 
-                           typename     A::template
-                              rebind >::other> impl_tree_t;
+                           typename allocator_traits::template portable_rebind_alloc
+                               >::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;
@@ -112,56 +130,56 @@ class flat_map
    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                           allocator_traits_type;
 
-   template
-   static D &force(const S &s)
-   {  return *const_cast(reinterpret_cast(&s)); }
 
-   template
-   static D force_copy(S s)
-   {
-      value_type *vp = reinterpret_cast(&*s);
-      return D(vp);
-   }
 
    /// @endcond
 
    public:
 
    // typedefs:
-   typedef typename impl_tree_t::key_type               key_type;
-   typedef T                                            mapped_type;
-   typedef typename std::pair    value_type;
-   typedef typename     A::pointer                      pointer;
-   typedef typename     A::const_pointer                const_pointer;
-   typedef typename     A::reference                    reference;
-   typedef typename     A::const_reference              const_reference;
-   typedef containers_detail::flat_tree_value_compare
+   typedef Key                                              key_type;
+   typedef T                                                mapped_type;
+   typedef typename std::pair        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
-      , containers_detail::select1st< std::pair >
-      , std::pair >                             value_compare;
-   typedef Pred                                         key_compare;
-   typedef typename containers_detail::
-      get_flat_tree_iterators::iterator        iterator;
-   typedef typename containers_detail::
-      get_flat_tree_iterators::const_iterator  const_iterator;
-   typedef typename containers_detail::
+      , container_detail::select1st< std::pair >
+      , std::pair >                                 value_compare;
+   typedef Pred                                             key_compare;
+   typedef typename container_detail::
+      get_flat_tree_iterators::iterator            iterator;
+   typedef typename container_detail::
+      get_flat_tree_iterators::const_iterator      const_iterator;
+   typedef typename container_detail::
       get_flat_tree_iterators
-         ::reverse_iterator                    reverse_iterator;
-   typedef typename containers_detail::
+         ::reverse_iterator                        reverse_iterator;
+   typedef typename container_detail::
       get_flat_tree_iterators
-         ::const_reverse_iterator              const_reverse_iterator;
-   typedef typename impl_tree_t::size_type              size_type;
-   typedef typename impl_tree_t::difference_type        difference_type;
-   typedef A                                        allocator_type;
-   typedef A                                        stored_allocator_type;
+         ::const_reverse_iterator                  const_reverse_iterator;
+   typedef A                                                allocator_type;
+   typedef A                                                stored_allocator_type;
+
+   public:
+   //! Effects: Default constructs an empty flat_map.
+   //! 
+   //! Complexity: Constant.
+   flat_map() 
+      : m_flat_tree() {}
 
    //! Effects: Constructs an empty flat_map using the specified
    //! comparison object and allocator.
    //! 
    //! Complexity: Constant.
-   explicit flat_map(const Pred& comp = Pred(), const allocator_type& a = allocator_type()) 
-      : m_flat_tree(comp, force(a)) {}
+   explicit flat_map(const Pred& comp, const allocator_type& a = allocator_type()) 
+      : m_flat_tree(comp, container_detail::force(a)) {}
 
    //! Effects: Constructs an empty flat_map using the specified comparison object and 
    //! allocator, and inserts elements from the range [first ,last ).
@@ -171,7 +189,7 @@ class flat_map
    template 
    flat_map(InputIterator first, InputIterator last, const Pred& comp = Pred(),
          const allocator_type& a = allocator_type())
-      : m_flat_tree(comp, force(a)) 
+      : m_flat_tree(comp, container_detail::force(a)) 
       { m_flat_tree.insert_unique(first, last); }
 
    //! Effects: Constructs an empty flat_map using the specified comparison object and 
@@ -224,27 +242,27 @@ class flat_map
    //! 
    //! Complexity: Constant.
    key_compare key_comp() const 
-      { return force(m_flat_tree.key_comp()); }
+      { return container_detail::force(m_flat_tree.key_comp()); }
 
    //! Effects: Returns an object of value_compare constructed out
    //!   of the comparison object.
    //! 
    //! Complexity: Constant.
    value_compare value_comp() const 
-      { return value_compare(force(m_flat_tree.key_comp())); }
+      { return value_compare(container_detail::force(m_flat_tree.key_comp())); }
 
    //! Effects: Returns a copy of the Allocator that
    //!   was passed to the object's constructor.
    //! 
    //! Complexity: Constant.
    allocator_type get_allocator() const 
-      { return force(m_flat_tree.get_allocator()); }
+      { return container_detail::force(m_flat_tree.get_allocator()); }
 
    const stored_allocator_type &get_stored_allocator() const 
-      { return force(m_flat_tree.get_stored_allocator()); }
+      { return container_detail::force(m_flat_tree.get_stored_allocator()); }
 
    stored_allocator_type &get_stored_allocator()
-      { return force(m_flat_tree.get_stored_allocator()); }
+      { return container_detail::force(m_flat_tree.get_stored_allocator()); }
 
    //! Effects: Returns an iterator to the first element contained in the container.
    //! 
@@ -252,7 +270,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    iterator begin() 
-      { return force_copy(m_flat_tree.begin()); }
+      { return container_detail::force_copy(m_flat_tree.begin()); }
 
    //! Effects: Returns a const_iterator to the first element contained in the container.
    //! 
@@ -260,7 +278,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    const_iterator begin() const 
-      { return force(m_flat_tree.begin()); }
+      { return container_detail::force(m_flat_tree.begin()); }
 
    //! Effects: Returns a const_iterator to the first element contained in the container.
    //! 
@@ -268,7 +286,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    const_iterator cbegin() const 
-      { return force(m_flat_tree.cbegin()); }
+      { return container_detail::force(m_flat_tree.cbegin()); }
 
    //! Effects: Returns an iterator to the end of the container.
    //! 
@@ -276,7 +294,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    iterator end() 
-      { return force_copy(m_flat_tree.end()); }
+      { return container_detail::force_copy(m_flat_tree.end()); }
 
    //! Effects: Returns a const_iterator to the end of the container.
    //! 
@@ -284,7 +302,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    const_iterator end() const 
-      { return force(m_flat_tree.end()); }
+      { return container_detail::force(m_flat_tree.end()); }
 
    //! Effects: Returns a const_iterator to the end of the container.
    //! 
@@ -292,7 +310,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    const_iterator cend() const 
-      { return force(m_flat_tree.cend()); }
+      { return container_detail::force(m_flat_tree.cend()); }
 
    //! Effects: Returns a reverse_iterator pointing to the beginning 
    //! of the reversed container. 
@@ -301,7 +319,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    reverse_iterator rbegin() 
-      { return force(m_flat_tree.rbegin()); }
+      { return container_detail::force(m_flat_tree.rbegin()); }
 
    //! Effects: Returns a const_reverse_iterator pointing to the beginning 
    //! of the reversed container. 
@@ -310,7 +328,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    const_reverse_iterator rbegin() const 
-      { return force(m_flat_tree.rbegin()); }
+      { return container_detail::force(m_flat_tree.rbegin()); }
 
    //! Effects: Returns a const_reverse_iterator pointing to the beginning 
    //! of the reversed container. 
@@ -319,7 +337,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    const_reverse_iterator crbegin() const 
-      { return force(m_flat_tree.crbegin()); }
+      { return container_detail::force(m_flat_tree.crbegin()); }
 
    //! Effects: Returns a reverse_iterator pointing to the end
    //! of the reversed container. 
@@ -328,7 +346,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    reverse_iterator rend() 
-      { return force(m_flat_tree.rend()); }
+      { return container_detail::force(m_flat_tree.rend()); }
 
    //! Effects: Returns a const_reverse_iterator pointing to the end
    //! of the reversed container. 
@@ -337,7 +355,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    const_reverse_iterator rend() const 
-      { return force(m_flat_tree.rend()); }
+      { return container_detail::force(m_flat_tree.rend()); }
 
    //! Effects: Returns a const_reverse_iterator pointing to the end
    //! of the reversed container. 
@@ -346,7 +364,7 @@ class flat_map
    //! 
    //! Complexity: Constant.
    const_reverse_iterator crend() const 
-      { return force(m_flat_tree.crend()); }
+      { return container_detail::force(m_flat_tree.crend()); }
 
    //! Effects: Returns true if the container contains no elements.
    //! 
@@ -372,20 +390,14 @@ class flat_map
    size_type max_size() const 
       { return m_flat_tree.max_size(); }
 
+   #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
    //! Effects: If there is no key equivalent to x in the flat_map, inserts 
    //!   value_type(x, T()) into the flat_map.
    //! 
    //! Returns: A reference to the mapped_type corresponding to x in *this.
    //! 
    //! Complexity: Logarithmic.
-   T &operator[](const key_type& k) 
-   {
-      iterator i = lower_bound(k);
-      // i->first is greater than or equivalent to k.
-      if (i == end() || key_comp()(k, (*i).first))
-         i = insert(i, value_type(k, T()));
-      return (*i).second;
-   }
+   mapped_type &operator[](const key_type& k);
 
    //! Effects: If there is no key equivalent to x in the flat_map, inserts 
    //! value_type(move(x), T()) into the flat_map (the key is move-constructed)
@@ -393,15 +405,11 @@ class flat_map
    //! Returns: A reference to the mapped_type corresponding to x in *this.
    //! 
    //! Complexity: Logarithmic.
-   T &operator[](BOOST_RV_REF(key_type) mk) 
-   {
-      key_type &k = mk;
-      iterator i = lower_bound(k);
-      // i->first is greater than or equivalent to k.
-      if (i == end() || key_comp()(k, (*i).first))
-         i = insert(i, value_type(boost::move(k), boost::move(T())));
-      return (*i).second;
-   }
+   mapped_type &operator[](key_type &&k) ;
+
+   #else
+   BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, priv_subscript)
+   #endif
 
    //! Returns: A reference to the element whose key is equivalent to x.
    //! Throws: An exception object of type out_of_range if no such element is present.
@@ -448,8 +456,8 @@ class flat_map
    //!
    //! Note: If an element it's inserted it might invalidate elements.
    std::pair insert(const value_type& x) 
-      { return force >(
-         m_flat_tree.insert_unique(force(x))); }
+      { return container_detail::force >(
+         m_flat_tree.insert_unique(container_detail::force(x))); }
 
    //! Effects: 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.
@@ -463,8 +471,8 @@ class flat_map
    //!
    //! Note: If an element it's inserted it might invalidate elements.
    std::pair insert(BOOST_RV_REF(value_type) x) 
-   {  return force >(
-      m_flat_tree.insert_unique(boost::move(force(x)))); }
+   {  return container_detail::force >(
+      m_flat_tree.insert_unique(boost::move(container_detail::force(x)))); }
 
    //! Effects: 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.
@@ -479,7 +487,7 @@ class flat_map
    //! Note: If an element it's inserted it might invalidate elements.
    std::pair insert(BOOST_RV_REF(impl_value_type) x) 
    {
-      return force >
+      return container_detail::force >
       (m_flat_tree.insert_unique(boost::move(x)));
    }
 
@@ -495,8 +503,8 @@ class flat_map
    //!
    //! Note: If an element it's inserted it might invalidate elements.
    iterator insert(const_iterator position, const value_type& x)
-      { return force_copy(
-         m_flat_tree.insert_unique(force(position), force(x))); }
+      { return container_detail::force_copy(
+         m_flat_tree.insert_unique(container_detail::force(position), container_detail::force(x))); }
 
    //! Effects: Inserts an element move constructed from x in the container.
    //!   p is a hint pointing to where the insert should start to search.
@@ -508,8 +516,8 @@ class flat_map
    //!
    //! Note: If an element it's inserted it might invalidate elements.
    iterator insert(const_iterator position, BOOST_RV_REF(value_type) x)
-      { return force_copy(
-         m_flat_tree.insert_unique(force(position), boost::move(force(x)))); }
+      { return container_detail::force_copy(
+         m_flat_tree.insert_unique(container_detail::force(position), boost::move(container_detail::force(x)))); }
 
    //! Effects: Inserts an element move constructed from x in the container.
    //!   p is a hint pointing to where the insert should start to search.
@@ -522,8 +530,8 @@ class flat_map
    //! Note: If an element it's inserted it might invalidate elements.
    iterator insert(const_iterator position, BOOST_RV_REF(impl_value_type) x)
    {
-      return force_copy(
-         m_flat_tree.insert_unique(force(position), boost::move(x)));
+      return container_detail::force_copy(
+         m_flat_tree.insert_unique(container_detail::force(position), boost::move(x)));
    }
 
    //! Requires: first, last are not iterators into *this.
@@ -539,7 +547,7 @@ class flat_map
    void insert(InputIterator first, InputIterator last) 
    {  m_flat_tree.insert_unique(first, last);  }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... if and only if there is no element in the container 
@@ -555,7 +563,7 @@ class flat_map
    //! Note: If an element it's inserted it might invalidate elements.
    template 
    iterator emplace(Args&&... args)
-   {  return force_copy(m_flat_tree.emplace_unique(boost::forward(args)...)); }
+   {  return container_detail::force_copy(m_flat_tree.emplace_unique(boost::forward(args)...)); }
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... in the container if and only if there is 
@@ -571,36 +579,27 @@ class flat_map
    //! Note: If an element it's inserted it might invalidate elements.
    template 
    iterator emplace_hint(const_iterator hint, Args&&... args)
-   {  return force_copy(m_flat_tree.emplace_hint_unique(force(hint), boost::forward(args)...)); }
+   {  return container_detail::force_copy(m_flat_tree.emplace_hint_unique(container_detail::force(hint), boost::forward(args)...)); }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
-   iterator emplace()
-   {  return force_copy(m_flat_tree.emplace_unique()); }
-
-   iterator emplace_hint(const_iterator hint)
-   {  return force_copy(m_flat_tree.emplace_hint_unique(force(hint))); }
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                                    \
-   template                                                         \
-   iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                            \
-   {                                                                                                  \
-      return force_copy(m_flat_tree.emplace_unique                                               \
-         (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)));                                 \
-   }                                                                                                  \
-                                                                                                      \
-   template                                                         \
-   iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))  \
-   {                                                                                                  \
-      return force_copy(m_flat_tree.emplace_hint_unique                                          \
-         (force(hint),                                                           \
-         BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)));                                  \
-   }                                                                                                  \
+   #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(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(m_flat_tree.emplace_hint_unique                                  \
+            (container_detail::force(hint)                                                      \
+               BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); }                \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Erases the element pointed to by position.
    //!
@@ -613,7 +612,7 @@ class flat_map
    //! Note: Invalidates elements with keys
    //!   not less than the erased element.
    iterator erase(const_iterator position) 
-      { return force_copy(m_flat_tree.erase(force(position))); }
+      { return container_detail::force_copy(m_flat_tree.erase(container_detail::force(position))); }
 
    //! Effects: Erases all elements in the container with key equivalent to x.
    //!
@@ -633,7 +632,7 @@ class flat_map
    //! Complexity: Logarithmic search time plus erasure time
    //!   linear to the elements with bigger keys.
    iterator erase(const_iterator first, const_iterator last)
-      { return force_copy(m_flat_tree.erase(force(first), force(last))); }
+      { return container_detail::force_copy(m_flat_tree.erase(container_detail::force(first), container_detail::force(last))); }
 
    //! Effects: erase(a.begin(),a.end()).
    //!
@@ -657,14 +656,14 @@ class flat_map
    //!
    //! Complexity: Logarithmic.
    iterator find(const key_type& x) 
-      { return force_copy(m_flat_tree.find(x)); }
+      { return container_detail::force_copy(m_flat_tree.find(x)); }
 
    //! Returns: A const_iterator pointing to an element with the key
    //!   equivalent to x, or end() if such an element is not found.
    //!
    //! Complexity: Logarithmic.s
    const_iterator find(const key_type& x) const 
-      { return force(m_flat_tree.find(x)); }
+      { return container_detail::force(m_flat_tree.find(x)); }
 
    //! Returns: The number of elements with key equivalent to x.
    //!
@@ -677,40 +676,40 @@ class flat_map
    //!
    //! Complexity: Logarithmic
    iterator lower_bound(const key_type& x) 
-      {  return force_copy(m_flat_tree.lower_bound(x)); }
+      {  return container_detail::force_copy(m_flat_tree.lower_bound(x)); }
 
    //! Returns: A const iterator pointing to the first element with key not
    //!   less than k, or a.end() if such an element is not found.
    //!
    //! Complexity: Logarithmic
    const_iterator lower_bound(const key_type& x) const 
-      {  return force(m_flat_tree.lower_bound(x)); }
+      {  return container_detail::force(m_flat_tree.lower_bound(x)); }
 
    //! Returns: An iterator pointing to the first element with key not less
    //!   than x, or end() if such an element is not found.
    //!
    //! Complexity: Logarithmic
    iterator upper_bound(const key_type& x) 
-      {  return force_copy(m_flat_tree.upper_bound(x)); }
+      {  return container_detail::force_copy(m_flat_tree.upper_bound(x)); }
 
    //! Returns: A const iterator pointing to the first element with key not
    //!   less than x, or end() if such an element is not found.
    //!
    //! Complexity: Logarithmic
    const_iterator upper_bound(const key_type& x) const 
-      {  return force(m_flat_tree.upper_bound(x)); }
+      {  return container_detail::force(m_flat_tree.upper_bound(x)); }
 
    //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
    //!
    //! Complexity: Logarithmic
    std::pair equal_range(const key_type& x) 
-      {  return force >(m_flat_tree.equal_range(x)); }
+      {  return container_detail::force >(m_flat_tree.equal_range(x)); }
 
    //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
    //!
    //! Complexity: Logarithmic
    std::pair equal_range(const key_type& x) const 
-      {  return force >(m_flat_tree.equal_range(x)); }
+      {  return container_detail::force >(m_flat_tree.equal_range(x)); }
 
    //! Effects: Number of elements for which memory has been allocated.
    //!   capacity() is always greater than or equal to size().
@@ -740,6 +739,29 @@ class flat_map
    template 
    friend bool operator< (const flat_map&,
                            const flat_map&);
+
+   private:
+   mapped_type &priv_subscript(const key_type& k)
+   {
+      iterator i = lower_bound(k);
+      // i->first is greater than or equivalent to k.
+      if (i == end() || key_comp()(k, (*i).first)){
+         container_detail::value_init m;
+         i = insert(i, impl_value_type(k, ::boost::move(m.m_t)));
+      }
+      return (*i).second;
+   }
+   mapped_type &priv_subscript(BOOST_RV_REF(key_type) mk) 
+   {
+      key_type &k = mk;
+      iterator i = lower_bound(k);
+      // i->first is greater than or equivalent to k.
+      if (i == end() || key_comp()(k, (*i).first)){
+         container_detail::value_init m;
+         i = insert(i, impl_value_type(boost::move(k), ::boost::move(m.m_t)));
+      }
+      return (*i).second;
+   }
    /// @endcond
 };
 
@@ -833,18 +855,18 @@ class flat_multimap
    /// @cond
    private:
    BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
-   typedef containers_detail::flat_tree, 
-                           containers_detail::select1st< std::pair >, 
+                           container_detail::select1st< std::pair >, 
                            Pred, 
                            A> tree_t;
    //This is the real tree stored here. It's based on a movable pair
-   typedef containers_detail::flat_tree, 
-                           containers_detail::select1st >, 
+   typedef container_detail::flat_tree, 
+                           container_detail::select1st >, 
                            Pred, 
-                           typename     A::template
-                              rebind >::other> impl_tree_t;
+                           typename allocator_traits::template portable_rebind_alloc
+                               >::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;
@@ -858,56 +880,55 @@ class flat_multimap
    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                           allocator_traits_type;
 
-   template
-   static D &force(const S &s)
-   {  return *const_cast((reinterpret_cast(&s))); }
-
-   template
-   static D force_copy(S s)
-   {
-      value_type *vp = reinterpret_cast(&*s);
-      return D(vp);
-   }
    /// @endcond
 
    public:
 
    // typedefs:
-   typedef typename impl_tree_t::key_type               key_type;
-   typedef T                                            mapped_type;
-   typedef typename std::pair    value_type;
-   typedef typename     A::pointer                      pointer;
-   typedef typename     A::const_pointer                const_pointer;
-   typedef typename     A::reference                    reference;
-   typedef typename     A::const_reference              const_reference;
-   typedef containers_detail::flat_tree_value_compare
+   typedef Key                                              key_type;
+   typedef T                                                mapped_type;
+   typedef Pred                                             key_compare;
+   typedef typename std::pair        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
-      , containers_detail::select1st< std::pair >
-      , std::pair >                             value_compare;
-   typedef Pred                                         key_compare;
-   typedef typename containers_detail::
-      get_flat_tree_iterators::iterator        iterator;
-   typedef typename containers_detail::
-      get_flat_tree_iterators::const_iterator  const_iterator;
-   typedef typename containers_detail::
+      , container_detail::select1st< std::pair >
+      , std::pair >                                 value_compare;
+
+   typedef typename container_detail::
+      get_flat_tree_iterators::iterator            iterator;
+   typedef typename container_detail::
+      get_flat_tree_iterators::const_iterator      const_iterator;
+   typedef typename container_detail::
       get_flat_tree_iterators
-         ::reverse_iterator                    reverse_iterator;
-   typedef typename containers_detail::
+         ::reverse_iterator                        reverse_iterator;
+   typedef typename container_detail::
       get_flat_tree_iterators
-         ::const_reverse_iterator              const_reverse_iterator;
-   typedef typename impl_tree_t::size_type              size_type;
-   typedef typename impl_tree_t::difference_type        difference_type;
-   typedef A                                        allocator_type;
-   typedef A                                        stored_allocator_type;
+         ::const_reverse_iterator                  const_reverse_iterator;
+   typedef A                                                allocator_type;
+   //Non-standard extension
+   typedef A                                                stored_allocator_type;
+
+   //! Effects: Default constructs an empty flat_map.
+   //! 
+   //! Complexity: Constant.
+   flat_multimap() 
+      : m_flat_tree() {}
 
    //! Effects: Constructs an empty flat_multimap using the specified comparison
    //!   object and allocator.
    //! 
    //! Complexity: Constant.
-   explicit flat_multimap(const Pred& comp = Pred(),
+   explicit flat_multimap(const Pred& comp,
                           const allocator_type& a = allocator_type())
-      : m_flat_tree(comp, force(a)) { }
+      : m_flat_tree(comp, container_detail::force(a)) { }
 
    //! Effects: Constructs an empty flat_multimap using the specified comparison object
    //!   and allocator, and inserts elements from the range [first ,last ).
@@ -918,7 +939,7 @@ class flat_multimap
    flat_multimap(InputIterator first, InputIterator last,
             const Pred& comp        = Pred(),
             const allocator_type& a = allocator_type())
-      : m_flat_tree(comp, force(a)) 
+      : m_flat_tree(comp, container_detail::force(a)) 
       { m_flat_tree.insert_equal(first, last); }
 
    //! Effects: Constructs an empty flat_multimap using the specified comparison object and 
@@ -967,27 +988,27 @@ class flat_multimap
    //! 
    //! Complexity: Constant.
    key_compare key_comp() const 
-      { return force(m_flat_tree.key_comp()); }
+      { return container_detail::force(m_flat_tree.key_comp()); }
 
    //! Effects: Returns an object of value_compare constructed out
    //!   of the comparison object.
    //! 
    //! Complexity: Constant.
    value_compare value_comp() const 
-      { return value_compare(force(m_flat_tree.key_comp())); }
+      { return value_compare(container_detail::force(m_flat_tree.key_comp())); }
 
    //! Effects: Returns a copy of the Allocator that
    //!   was passed to the object's constructor.
    //! 
    //! Complexity: Constant.
    allocator_type get_allocator() const 
-      { return force(m_flat_tree.get_allocator()); }
+      { return container_detail::force(m_flat_tree.get_allocator()); }
 
    const stored_allocator_type &get_stored_allocator() const 
-      { return force(m_flat_tree.get_stored_allocator()); }
+      { return container_detail::force(m_flat_tree.get_stored_allocator()); }
 
    stored_allocator_type &get_stored_allocator()
-      { return force(m_flat_tree.get_stored_allocator()); }
+      { return container_detail::force(m_flat_tree.get_stored_allocator()); }
 
    //! Effects: Returns an iterator to the first element contained in the container.
    //! 
@@ -995,7 +1016,7 @@ class flat_multimap
    //! 
    //! Complexity: Constant.
    iterator begin() 
-      { return force_copy(m_flat_tree.begin()); }
+      { return container_detail::force_copy(m_flat_tree.begin()); }
 
    //! Effects: Returns a const_iterator to the first element contained in the container.
    //! 
@@ -1003,7 +1024,7 @@ class flat_multimap
    //! 
    //! Complexity: Constant.
    const_iterator begin() const 
-      { return force(m_flat_tree.begin()); }
+      { return container_detail::force(m_flat_tree.begin()); }
 
    //! Effects: Returns an iterator to the end of the container.
    //! 
@@ -1011,7 +1032,7 @@ class flat_multimap
    //! 
    //! Complexity: Constant.
    iterator end() 
-      { return force_copy(m_flat_tree.end()); }
+      { return container_detail::force_copy(m_flat_tree.end()); }
 
    //! Effects: Returns a const_iterator to the end of the container.
    //! 
@@ -1019,7 +1040,7 @@ class flat_multimap
    //! 
    //! Complexity: Constant.
    const_iterator end() const 
-      { return force(m_flat_tree.end()); }
+      { return container_detail::force(m_flat_tree.end()); }
 
    //! Effects: Returns a reverse_iterator pointing to the beginning 
    //! of the reversed container. 
@@ -1028,7 +1049,7 @@ class flat_multimap
    //! 
    //! Complexity: Constant.
    reverse_iterator rbegin() 
-      { return force(m_flat_tree.rbegin()); }
+      { return container_detail::force(m_flat_tree.rbegin()); }
 
    //! Effects: Returns a const_reverse_iterator pointing to the beginning 
    //! of the reversed container. 
@@ -1037,7 +1058,7 @@ class flat_multimap
    //! 
    //! Complexity: Constant.
    const_reverse_iterator rbegin() const 
-      { return force(m_flat_tree.rbegin()); }
+      { return container_detail::force(m_flat_tree.rbegin()); }
 
    //! Effects: Returns a reverse_iterator pointing to the end
    //! of the reversed container. 
@@ -1046,7 +1067,7 @@ class flat_multimap
    //! 
    //! Complexity: Constant.
    reverse_iterator rend() 
-      { return force(m_flat_tree.rend()); }
+      { return container_detail::force(m_flat_tree.rend()); }
 
    //! Effects: Returns a const_reverse_iterator pointing to the end
    //! of the reversed container. 
@@ -1055,7 +1076,7 @@ class flat_multimap
    //! 
    //! Complexity: Constant.
    const_reverse_iterator rend() const 
-      { return force(m_flat_tree.rend()); }
+      { return container_detail::force(m_flat_tree.rend()); }
 
    //! Effects: Returns true if the container contains no elements.
    //! 
@@ -1098,7 +1119,7 @@ class flat_multimap
    //!
    //! Note: If an element it's inserted it might invalidate elements.
    iterator insert(const value_type& x) 
-      { return force_copy(m_flat_tree.insert_equal(force(x))); }
+      { return container_detail::force_copy(m_flat_tree.insert_equal(container_detail::force(x))); }
 
    //! Effects: Inserts a new value move-constructed from x and returns 
    //!   the iterator pointing to the newly inserted element. 
@@ -1108,7 +1129,7 @@ class flat_multimap
    //!
    //! Note: If an element it's inserted it might invalidate elements.
    iterator insert(BOOST_RV_REF(value_type) x) 
-   { return force_copy(m_flat_tree.insert_equal(boost::move(x))); }
+   { return container_detail::force_copy(m_flat_tree.insert_equal(boost::move(x))); }
 
    //! Effects: Inserts a new value move-constructed from x and returns 
    //!   the iterator pointing to the newly inserted element. 
@@ -1118,7 +1139,7 @@ class flat_multimap
    //!
    //! Note: If an element it's inserted it might invalidate elements.
    iterator insert(BOOST_RV_REF(impl_value_type) x) 
-      { return force_copy(m_flat_tree.insert_equal(boost::move(x))); }
+      { return container_detail::force_copy(m_flat_tree.insert_equal(boost::move(x))); }
 
    //! Effects: Inserts a copy of x in the container.
    //!   p is a hint pointing to where the insert should start to search.
@@ -1132,7 +1153,7 @@ class flat_multimap
    //!
    //! Note: If an element it's inserted it might invalidate elements.
    iterator insert(const_iterator position, const value_type& x) 
-      { return force_copy(m_flat_tree.insert_equal(force(position), force(x))); }
+      { return container_detail::force_copy(m_flat_tree.insert_equal(container_detail::force(position), container_detail::force(x))); }
 
    //! Effects: Inserts a value move constructed from x in the container.
    //!   p is a hint pointing to where the insert should start to search.
@@ -1147,8 +1168,8 @@ class flat_multimap
    //! Note: If an element it's inserted it might invalidate elements.
    iterator insert(const_iterator position, BOOST_RV_REF(value_type) x) 
    {
-      return force_copy
-         (m_flat_tree.insert_equal(force(position)
+      return container_detail::force_copy
+         (m_flat_tree.insert_equal(container_detail::force(position)
                                   , boost::move(x)));
    }
 
@@ -1165,8 +1186,8 @@ class flat_multimap
    //! Note: If an element it's inserted it might invalidate elements.
    iterator insert(const_iterator position, BOOST_RV_REF(impl_value_type) x) 
    {
-      return force_copy(
-         m_flat_tree.insert_equal(force(position), boost::move(x)));
+      return container_detail::force_copy(
+         m_flat_tree.insert_equal(container_detail::force(position), boost::move(x)));
    }
 
    //! Requires: first, last are not iterators into *this.
@@ -1181,7 +1202,7 @@ class flat_multimap
    void insert(InputIterator first, InputIterator last) 
       {  m_flat_tree.insert_equal(first, last); }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... and returns the iterator pointing to the
@@ -1193,7 +1214,7 @@ class flat_multimap
    //! Note: If an element it's inserted it might invalidate elements.
    template 
    iterator emplace(Args&&... args)
-   {  return force_copy(m_flat_tree.emplace_equal(boost::forward(args)...)); }
+   {  return container_detail::force_copy(m_flat_tree.emplace_equal(boost::forward(args)...)); }
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... in the container.
@@ -1210,38 +1231,29 @@ class flat_multimap
    template 
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {
-      return force_copy(m_flat_tree.emplace_hint_equal
-         (force(hint), boost::forward(args)...));
+      return container_detail::force_copy(m_flat_tree.emplace_hint_equal
+         (container_detail::force(hint), boost::forward(args)...));
    }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
-   iterator emplace()
-   {  return force_copy(m_flat_tree.emplace_equal()); }
-
-   iterator emplace_hint(const_iterator hint)
-   {  return force_copy(m_flat_tree.emplace_hint_equal(force(hint))); }
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                                    \
-   template                                                         \
-   iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                            \
-   {                                                                                                  \
-      return force_copy(m_flat_tree.emplace_equal                                                \
-         (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)));                                 \
-   }                                                                                                  \
-                                                                                                      \
-   template                                                         \
-   iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))  \
-   {                                                                                                  \
-      return force_copy(m_flat_tree.emplace_hint_equal                                           \
-         (force(hint),                                                           \
-            BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)));                               \
-   }                                                                                                  \
+   #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(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(m_flat_tree.emplace_hint_equal                                   \
+            (container_detail::force(hint)                                                      \
+               BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); }                \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Erases the element pointed to by position.
    //!
@@ -1254,7 +1266,7 @@ class flat_multimap
    //! Note: Invalidates elements with keys
    //!   not less than the erased element.
    iterator erase(const_iterator position) 
-      { return force_copy(m_flat_tree.erase(force(position))); }
+      { return container_detail::force_copy(m_flat_tree.erase(container_detail::force(position))); }
 
    //! Effects: Erases all elements in the container with key equivalent to x.
    //!
@@ -1274,7 +1286,7 @@ class flat_multimap
    //! Complexity: Logarithmic search time plus erasure time
    //!   linear to the elements with bigger keys.
    iterator erase(const_iterator first, const_iterator last)
-      { return force_copy(m_flat_tree.erase(force(first), force(last))); }
+      { return container_detail::force_copy(m_flat_tree.erase(container_detail::force(first), container_detail::force(last))); }
 
    //! Effects: erase(a.begin(),a.end()).
    //!
@@ -1298,14 +1310,14 @@ class flat_multimap
    //!
    //! Complexity: Logarithmic.
    iterator find(const key_type& x)
-      { return force_copy(m_flat_tree.find(x)); }
+      { return container_detail::force_copy(m_flat_tree.find(x)); }
 
    //! Returns: An const_iterator pointing to an element with the key
    //!   equivalent to x, or end() if such an element is not found.
    //!
    //! Complexity: Logarithmic.
    const_iterator find(const key_type& x) const 
-      { return force(m_flat_tree.find(x)); }
+      { return container_detail::force(m_flat_tree.find(x)); }
 
    //! Returns: The number of elements with key equivalent to x.
    //!
@@ -1318,41 +1330,41 @@ class flat_multimap
    //!
    //! Complexity: Logarithmic
    iterator lower_bound(const key_type& x) 
-      {return force_copy(m_flat_tree.lower_bound(x)); }
+      {return container_detail::force_copy(m_flat_tree.lower_bound(x)); }
 
    //! Returns: A const iterator pointing to the first element with key
    //!   not less than k, or a.end() if such an element is not found.
    //!
    //! Complexity: Logarithmic
    const_iterator lower_bound(const key_type& x) const 
-      {  return force(m_flat_tree.lower_bound(x));  }
+      {  return container_detail::force(m_flat_tree.lower_bound(x));  }
 
    //! Returns: An iterator pointing to the first element with key not less
    //!   than x, or end() if such an element is not found.
    //!
    //! Complexity: Logarithmic
    iterator upper_bound(const key_type& x) 
-      {return force_copy(m_flat_tree.upper_bound(x)); }
+      {return container_detail::force_copy(m_flat_tree.upper_bound(x)); }
 
    //! Returns: A const iterator pointing to the first element with key
    //!   not less than x, or end() if such an element is not found.
    //!
    //! Complexity: Logarithmic
    const_iterator upper_bound(const key_type& x) const 
-      {  return force(m_flat_tree.upper_bound(x)); }
+      {  return container_detail::force(m_flat_tree.upper_bound(x)); }
 
    //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
    //!
    //! Complexity: Logarithmic
    std::pair equal_range(const key_type& x) 
-      {  return force_copy >(m_flat_tree.equal_range(x));   }
+      {  return container_detail::force_copy >(m_flat_tree.equal_range(x));   }
 
    //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
    //!
    //! Complexity: Logarithmic
    std::pair 
       equal_range(const key_type& x) const 
-      {  return force_copy >(m_flat_tree.equal_range(x));   }
+      {  return container_detail::force_copy >(m_flat_tree.equal_range(x));   }
 
    //! Effects: Number of elements for which memory has been allocated.
    //!   capacity() is always greater than or equal to size().
@@ -1440,4 +1452,4 @@ struct has_trivial_destructor_after_move< boost::container::flat_multimap
 
-#endif /* BOOST_CONTAINERS_FLAT_MAP_HPP */
+#endif /* BOOST_CONTAINER_FLAT_MAP_HPP */
diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp
index 694a072..07e1f1f 100644
--- a/include/boost/container/flat_set.hpp
+++ b/include/boost/container/flat_set.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_FLAT_SET_HPP
-#define BOOST_CONTAINERS_FLAT_SET_HPP
+#ifndef BOOST_CONTAINER_FLAT_SET_HPP
+#define BOOST_CONTAINER_FLAT_SET_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -74,9 +74,9 @@ class flat_set
    /// @cond
    private:
    BOOST_COPYABLE_AND_MOVABLE(flat_set)
-   typedef containers_detail::flat_tree, Pred, A> tree_t;
+   typedef container_detail::flat_tree, Pred, A> tree_t;
    tree_t m_flat_tree;  // flat tree representing flat_set
-   typedef typename containers_detail::
+   typedef typename container_detail::
       move_const_ref_type::type insert_const_ref_type;
    /// @endcond
 
@@ -100,11 +100,18 @@ class flat_set
    typedef typename tree_t::allocator_type         allocator_type;
    typedef typename tree_t::stored_allocator_type  stored_allocator_type;
 
+   //! Effects: Defatuls constructs an empty flat_map.
+   //! 
+   //! Complexity: Constant.
+   explicit flat_set()
+      : m_flat_tree()
+   {}
+
    //! Effects: Constructs an empty flat_map using the specified
    //! comparison object and allocator.
    //! 
    //! Complexity: Constant.
-   explicit flat_set(const Pred& comp = Pred(),
+   explicit flat_set(const Pred& comp,
                      const allocator_type& a = allocator_type())
       : m_flat_tree(comp, a)
    {}
@@ -344,7 +351,7 @@ class flat_set
    { return this->insert(const_cast(x)); }
 
    template
-   std::pair insert(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   std::pair insert(const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return priv_insert(u); }
    #endif
 
@@ -381,7 +388,7 @@ class flat_set
    { return this->insert(position, const_cast(x)); }
 
    template
-   iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return priv_insert(position, u); }
    #endif
 
@@ -410,7 +417,7 @@ class flat_set
    void insert(InputIterator first, InputIterator last) 
       {  m_flat_tree.insert_unique(first, last);  }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... if and only if there is no element in the container 
@@ -444,27 +451,23 @@ class flat_set
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {  return m_flat_tree.emplace_hint_unique(hint, boost::forward(args)...); }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
-   iterator emplace()
-   {  return m_flat_tree.emplace_unique(); }
-
-   iterator emplace_hint(const_iterator hint)
-   {  return m_flat_tree.emplace_hint_unique(hint); }
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                                             \
-   template                                                                  \
-   iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                                     \
-   {  return m_flat_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }           \
-                                                                                                               \
-   template                                                                  \
-   iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))           \
-   {  return m_flat_tree.emplace_hint_unique(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }\
+   #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_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, _)); }              \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Erases the element pointed to by position.
    //!
@@ -702,9 +705,9 @@ class flat_multiset
    /// @cond
    private:
    BOOST_COPYABLE_AND_MOVABLE(flat_multiset)
-   typedef containers_detail::flat_tree, Pred, A> tree_t;
+   typedef container_detail::flat_tree, Pred, A> tree_t;
    tree_t m_flat_tree;  // flat tree representing flat_multiset
-   typedef typename containers_detail::
+   typedef typename container_detail::
       move_const_ref_type::type insert_const_ref_type;
    /// @endcond
 
@@ -727,8 +730,14 @@ class flat_multiset
    typedef typename tree_t::allocator_type         allocator_type;
    typedef typename tree_t::stored_allocator_type  stored_allocator_type;
 
-   // allocation/deallocation
-   explicit flat_multiset(const Pred& comp = Pred(),
+   //! Effects: Defatuls constructs an empty flat_map.
+   //! 
+   //! Complexity: Constant.
+   explicit flat_multiset()
+      : m_flat_tree()
+   {}
+
+   explicit flat_multiset(const Pred& comp,
                           const allocator_type& a = allocator_type())
       : m_flat_tree(comp, a) {}
 
@@ -943,7 +952,7 @@ class flat_multiset
    { return this->insert(const_cast(x)); }
 
    template
-   iterator insert(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   iterator insert(const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return priv_insert(u); }
    #endif
 
@@ -975,7 +984,7 @@ class flat_multiset
    { return this->insert(position, const_cast(x)); }
 
    template
-   iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return priv_insert(position, u); }
    #endif
 
@@ -1004,7 +1013,7 @@ class flat_multiset
    void insert(InputIterator first, InputIterator last) 
       {  m_flat_tree.insert_equal(first, last);  }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... and returns the iterator pointing to the
@@ -1033,27 +1042,23 @@ class flat_multiset
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {  return m_flat_tree.emplace_hint_equal(hint, boost::forward(args)...); }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
-   iterator emplace()
-   {  return m_flat_tree.emplace_equal(); }
-
-   iterator emplace_hint(const_iterator hint)
-   {  return m_flat_tree.emplace_hint_equal(hint); }
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                                             \
-   template                                                                  \
-   iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                                     \
-   {  return m_flat_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }            \
-                                                                                                               \
-   template                                                                  \
-   iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))           \
-   {  return m_flat_tree.emplace_hint_equal(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); } \
+   #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 (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Erases the element pointed to by position.
    //!
@@ -1258,4 +1263,4 @@ namespace container {
 
 #include 
 
-#endif /* BOOST_CONTAINERS_FLAT_SET_HPP */
+#endif /* BOOST_CONTAINER_FLAT_SET_HPP */
diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp
index ad4aecf..03ba7f1 100644
--- a/include/boost/container/list.hpp
+++ b/include/boost/container/list.hpp
@@ -7,8 +7,8 @@
 // See http://www.boost.org/libs/container for documentation.
 //
 
-#ifndef BOOST_CONTAINERS_LIST_HPP_
-#define BOOST_CONTAINERS_LIST_HPP_
+#ifndef BOOST_CONTAINER_LIST_HPP_
+#define BOOST_CONTAINER_LIST_HPP_
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -20,15 +20,16 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
-#if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 #else
 //Preprocessor library to emulate perfect forwarding
 #include  
@@ -51,13 +52,13 @@ namespace container {
 #endif
 
 /// @cond
-namespace containers_detail {
+namespace container_detail {
 
 template
 struct list_hook
 {
-   typedef typename containers_detail::bi::make_list_base_hook
-      , containers_detail::bi::link_mode >::type type;
+   typedef typename container_detail::bi::make_list_base_hook
+      , container_detail::bi::link_mode >::type type;
 };
 
 template 
@@ -65,33 +66,28 @@ struct list_node
    :  public list_hook::type
 {
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
-
    list_node()
       : m_data()
    {}
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    template
    list_node(Args &&...args)
       : m_data(boost::forward(args)...)
    {}
 
-   #else //#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
-
-   list_node()
-      : m_data()
-   {}
+   #else //#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
 
    #define BOOST_PP_LOCAL_MACRO(n)                                                           \
    template                                                \
-   list_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                          \
-      : m_data(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))                     \
+   list_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                          \
+      : m_data(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))                     \
    {}                                                                                        \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif//#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif//#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
 
    T m_data;
 };
@@ -99,21 +95,25 @@ struct list_node
 template
 struct intrusive_list_type
 {
-   typedef typename A::value_type               value_type;
-   typedef typename boost::pointer_to_other
-      ::type         void_pointer;
-   typedef typename containers_detail::list_node
+   typedef boost::container::allocator_traits   allocator_traits_type;
+   typedef typename allocator_traits_type::value_type value_type;
+   typedef typename boost::intrusive::pointer_traits
+      ::template
+         rebind_pointer::type
+            void_pointer;
+   typedef typename container_detail::list_node
                       node_type;
-   typedef typename containers_detail::bi::make_list
+   typedef typename container_detail::bi::make_list
       < node_type
-      , containers_detail::bi::base_hook::type>
-      , containers_detail::bi::constant_time_size
-      , containers_detail::bi::size_type
+      , container_detail::bi::base_hook::type>
+      , container_detail::bi::constant_time_size
+      , container_detail::bi::size_type
+         
       >::type                                   container_type;
    typedef container_type                       type ;
 };
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 /// @endcond
 
 //! A list is a doubly linked list. That is, it is a Sequence that supports both
@@ -132,22 +132,23 @@ template  >
 template 
 #endif
 class list 
-   : protected containers_detail::node_alloc_holder
-      ::type>
+   : protected container_detail::node_alloc_holder
+      ::type>
 {
    /// @cond
    typedef typename 
-      containers_detail::intrusive_list_type::type Icont;
+      container_detail::intrusive_list_type::type Icont;
    typedef list                                 ThisType;
-   typedef containers_detail::node_alloc_holder        AllocHolder;
+   typedef container_detail::node_alloc_holder        AllocHolder;
    typedef typename AllocHolder::NodePtr              NodePtr;
    typedef typename AllocHolder::NodeAlloc            NodeAlloc;
    typedef typename AllocHolder::ValAlloc             ValAlloc;
    typedef typename AllocHolder::Node                 Node;
-   typedef containers_detail::allocator_destroyer     Destroyer;
+   typedef container_detail::allocator_destroyer     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_traits_type;
 
    class equal_to_value
    {
@@ -181,23 +182,23 @@ class list
 
    public:
    //! The type of object, T, stored in the list
-   typedef T                                       value_type;
+   typedef T                                                value_type;
    //! Pointer to T
-   typedef typename A::pointer                     pointer;
+   typedef typename allocator_traits_type::pointer          pointer;
    //! Const pointer to T
-   typedef typename A::const_pointer               const_pointer;
+   typedef typename allocator_traits_type::const_pointer    const_pointer;
    //! Reference to T
-   typedef typename A::reference                   reference;
+   typedef typename allocator_traits_type::reference        reference;
    //! Const reference to T
-   typedef typename A::const_reference             const_reference;
+   typedef typename allocator_traits_type::const_reference  const_reference;
    //! An unsigned integral type
-   typedef typename A::size_type                   size_type;
+   typedef typename allocator_traits_type::size_type        size_type;
    //! A signed integral type
-   typedef typename A::difference_type             difference_type;
+   typedef typename allocator_traits_type::difference_type  difference_type;
    //! The allocator type
-   typedef A                                       allocator_type;
-   //! The stored allocator type
-   typedef NodeAlloc                               stored_allocator_type;
+   typedef A                                                allocator_type;
+   //! Non-standard extension: the stored allocator type
+   typedef NodeAlloc                                        stored_allocator_type;
 
    /// @cond
    private:
@@ -313,12 +314,21 @@ class list
    //! Const iterator used to iterate backwards through a list. 
    typedef std::reverse_iterator  const_reverse_iterator;
 
+   //! Effects: Default constructs a list.
+   //! 
+   //! Throws: If allocator_type's default constructor throws.
+   //! 
+   //! Complexity: Constant.
+   list() 
+      : AllocHolder()
+   {}
+
    //! Effects: Constructs a list taking the allocator as parameter.
    //! 
    //! Throws: If allocator_type's copy constructor throws.
    //! 
    //! Complexity: Constant.
-   explicit list(const allocator_type &a = A()) 
+   explicit list(const allocator_type &a)
       : AllocHolder(a)
    {}
 
@@ -329,7 +339,7 @@ class list
    //!   throws or T's default or copy constructor throws.
    //! 
    //! Complexity: Linear to n.
-   list(size_type n)
+   explicit list(size_type n)
       : AllocHolder(A())
    {  this->resize(n);  }
 
@@ -533,7 +543,6 @@ class list
    size_type max_size() const 
    {  return AllocHolder::max_size();  }
 
-
    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
    //! Effects: Inserts a copy of x at the beginning of the list.
    //!
@@ -711,7 +720,15 @@ class list
    //! Complexity: Linear to the number of elements in x.
    ThisType& operator=(BOOST_COPY_ASSIGN_REF(ThisType) x)
    {
-      if (this != &x) {
+      if (&x != this){
+         NodeAlloc &this_alloc     = this->node_alloc();
+         const NodeAlloc &x_alloc  = x.node_alloc();
+         container_detail::bool_ flag;
+         if(flag && this_alloc != x_alloc){
+            this->clear();
+         }
+         this->AllocHolder::copy_assign_alloc(x);
          this->assign(x.begin(), x.end());
       }
       return *this;
@@ -725,10 +742,26 @@ class list
    //! Throws: If allocator_type's copy constructor throws.
    //!
    //! Complexity: Constant.
-   ThisType& operator=(BOOST_RV_REF(ThisType) mx)
+   ThisType& operator=(BOOST_RV_REF(ThisType) x)
    {
-      this->clear();
-      this->swap(mx);
+      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_category ItCat;
+            this->assign( boost::make_move_iterator(x.begin())
+                        , boost::make_move_iterator(x.end()));
+         }
+      }
       return *this;
    }
 
@@ -753,8 +786,8 @@ class list
    template 
    void insert(const_iterator p, InpIt first, InpIt last) 
    {
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_insert_dispatch(p, first, last, Result());
    }
 
@@ -780,7 +813,7 @@ class list
    BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator)
    #endif
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... in the end of the list.
@@ -818,57 +851,40 @@ class list
    template 
    iterator emplace(const_iterator p, Args&&... args)
    {
-      typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator());
-      new ((void*)containers_detail::get_pointer(d.get())) Node(boost::forward(args)...);
-      NodePtr node = d.get();
-      d.release();
-      return iterator(this->icont().insert(p.get(), *node));
+      NodePtr pnode(AllocHolder::create_node(boost::forward(args)...));
+      return iterator(this->icont().insert(p.get(), *pnode));
    }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
-
-   //0 args
-   void emplace_back()
-   {  this->emplace(this->cend());  }
-
-   void emplace_front()
-   {  this->emplace(this->cbegin());   }
-
-   iterator emplace(const_iterator p)
-   {
-      typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator());
-      new ((void*)containers_detail::get_pointer(d.get())) Node();
-      NodePtr node = d.get();
-      d.release();
-      return iterator(this->icont().insert(p.get(), *node));
-   }
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    #define BOOST_PP_LOCAL_MACRO(n)                                                              \
-   template                                                   \
-   void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_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, _))                        \
    {                                                                                            \
-      this->emplace(this->cend(), BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));    \
+      this->emplace(this->cend()                                                                \
+                    BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));            \
    }                                                                                            \
                                                                                                 \
-   template                                                   \
-   void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                    \
-   {  this->emplace(this->cbegin(), BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));} \
-                                                                                                \
-   template                                                   \
-   iterator emplace(const_iterator p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_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, _))                       \
    {                                                                                            \
-      typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator());          \
-      new ((void*)containers_detail::get_pointer(d.get()))                                                 \
-         Node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                        \
-      NodePtr node = d.get();                                                                   \
-      d.release();                                                                              \
-      return iterator(this->icont().insert(p.get(), *node));                                    \
+      this->emplace(this->cbegin()                                                              \
+                    BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));            \
+   }                                                                                            \
+                                                                                                \
+   BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >)       \
+   iterator emplace(const_iterator p                                                            \
+                    BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                \
+   {                                                                                            \
+      NodePtr pnode (AllocHolder::create_node                                                   \
+         (BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)));                              \
+      return iterator(this->icont().insert(p.get(), *pnode));                                   \
    }                                                                                            \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Requires: p must be a valid iterator of *this.
    //!
@@ -907,8 +923,8 @@ class list
    template 
    void assign(InpIt first, InpIt last) 
    {
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_assign_dispatch(first, last, Result());
    }
 
@@ -925,14 +941,10 @@ class list
    //! 
    //! Note: 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) 
+   void splice(const_iterator p, ThisType& x) BOOST_CONTAINER_NOEXCEPT
    {
-      if((NodeAlloc&)*this == (NodeAlloc&)x){
-         this->icont().splice(p.get(), x.icont());
-      }
-      else{
-         throw std::runtime_error("list::splice called with unequal allocators");
-      }
+      BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x);
+      this->icont().splice(p.get(), x.icont());
    }
 
    //! Requires: p must point to an element contained
@@ -949,14 +961,10 @@ class list
    //! 
    //! Note: 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) 
+   void splice(const_iterator p, ThisType &x, const_iterator i) BOOST_CONTAINER_NOEXCEPT
    {
-      if((NodeAlloc&)*this == (NodeAlloc&)x){
-         this->icont().splice(p.get(), x.icont(), i.get());
-      }
-      else{
-         throw std::runtime_error("list::splice called with unequal allocators");
-      }
+      BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x);
+      this->icont().splice(p.get(), x.icont(), i.get());
    }
 
    //! Requires: p must point to an element contained
@@ -972,14 +980,10 @@ class list
    //! 
    //! Note: 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) 
+   void splice(const_iterator p, ThisType &x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
    {
-      if((NodeAlloc&)*this == (NodeAlloc&)x){
-         this->icont().splice(p.get(), x.icont(), first.get(), last.get());
-      }
-      else{
-         throw std::runtime_error("list::splice called with unequal allocators");
-      }
+      BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x);
+      this->icont().splice(p.get(), x.icont(), first.get(), last.get());
    }
 
    //! Requires: p must point to an element contained
@@ -996,14 +1000,10 @@ class list
    //! 
    //! Note: 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) 
+   void splice(const_iterator p, ThisType &x, const_iterator first, const_iterator last, size_type n) BOOST_CONTAINER_NOEXCEPT
    {
-      if((NodeAlloc&)*this == (NodeAlloc&)x){
-         this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n);
-      }
-      else{
-         throw std::runtime_error("list::splice called with unequal allocators");
-      }
+      BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x);
+      this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n);
    }
 
    //! Effects: Reverses the order of elements in the list. 
@@ -1240,11 +1240,11 @@ class list
    template 
    void priv_insert_dispatch(const_iterator p,
                              InputIter first, InputIter last,
-                             containers_detail::false_)
+                             container_detail::false_)
    {  this->priv_create_and_insert_nodes(p, first, last);   }
 
    template
-   void priv_insert_dispatch(const_iterator p, Integer n, Integer x, containers_detail::true_) 
+   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) 
@@ -1262,11 +1262,11 @@ class list
    }
 
    template 
-   void priv_assign_dispatch(Integer n, Integer val, containers_detail::true_)
+   void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
    {  this->priv_fill_assign((size_type) n, (T) val); }
 
    template 
-   void priv_assign_dispatch(InputIter first2, InputIter last2, containers_detail::false_)
+   void priv_assign_dispatch(InputIter first2, InputIter last2, container_detail::false_)
    {
       iterator first1   = this->begin();
       iterator last1    = this->end();
@@ -1370,4 +1370,4 @@ namespace container {
 
 #include 
 
-#endif // BOOST_CONTAINERS_LIST_HPP_
+#endif // BOOST_CONTAINER_LIST_HPP_
diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp
index 9eac512..63717d9 100644
--- a/include/boost/container/map.hpp
+++ b/include/boost/container/map.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_MAP_HPP
-#define BOOST_CONTAINERS_MAP_HPP
+#ifndef BOOST_CONTAINER_MAP_HPP
+#define BOOST_CONTAINER_MAP_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -31,7 +31,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
+
 
 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
 namespace boost {
@@ -74,9 +77,9 @@ class map
    /// @cond
    private:
    BOOST_COPYABLE_AND_MOVABLE(map)
-   typedef containers_detail::rbtree, 
-                           containers_detail::select1st< std::pair >, 
+                           container_detail::select1st< std::pair >, 
                            Pred, 
                            A> tree_t;
    tree_t m_tree;  // red-black tree representing map
@@ -103,7 +106,7 @@ class map
    typedef typename tree_t::allocator_type         allocator_type;
    typedef typename tree_t::stored_allocator_type  stored_allocator_type;
    typedef std::pair        nonconst_value_type;
-   typedef containers_detail::pair
+   typedef container_detail::pair
                             nonconst_impl_value_type;
 
    /// @cond
@@ -122,16 +125,26 @@ class map
    /// @endcond
    typedef value_compare_impl             value_compare;
 
+   //! Effects: Default constructs an empty map.
+   //! 
+   //! Complexity: Constant.
+   map()
+      : m_tree()
+   {
+      //Allocator type must be std::pair
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename A::value_type>::value));
+   }
+
    //! Effects: Constructs an empty map using the specified comparison object 
    //! and allocator.
    //! 
    //! Complexity: Constant.
-   explicit map(const Pred& comp = Pred(),
+   explicit map(const Pred& comp,
                 const allocator_type& a = allocator_type())
       : m_tree(comp, a)
    {
       //Allocator type must be std::pair
-      BOOST_STATIC_ASSERT((containers_detail::is_same, typename     A::value_type>::value));
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename A::value_type>::value));
    }
 
    //! Effects: Constructs an empty map using the specified comparison object and 
@@ -145,7 +158,7 @@ class map
       : m_tree(first, last, comp, a, true) 
    {
       //Allocator type must be std::pair
-      BOOST_STATIC_ASSERT((containers_detail::is_same, typename     A::value_type>::value));
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename     A::value_type>::value));
    }
 
    //! Effects: Constructs an empty map using the specified comparison object and 
@@ -162,7 +175,7 @@ class map
       : m_tree(ordered_range, first, last, comp, a) 
    {
       //Allocator type must be std::pair
-      BOOST_STATIC_ASSERT((containers_detail::is_same, typename     A::value_type>::value));
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename     A::value_type>::value));
    }
 
    //! Effects: Copy constructs a map.
@@ -172,7 +185,7 @@ class map
       : m_tree(x.m_tree)
    {
       //Allocator type must be std::pair
-      BOOST_STATIC_ASSERT((containers_detail::is_same, typename     A::value_type>::value));
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename     A::value_type>::value));
    }
 
    //! Effects: Move constructs a map. Constructs *this using x's resources.
@@ -184,7 +197,7 @@ class map
       : m_tree(boost::move(x.m_tree))
    {
       //Allocator type must be std::pair
-      BOOST_STATIC_ASSERT((containers_detail::is_same, typename     A::value_type>::value));
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename     A::value_type>::value));
    }
 
    //! Effects: Makes *this a copy of x.
@@ -318,24 +331,14 @@ class map
    size_type max_size() const 
    { return m_tree.max_size(); }
 
+   #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.
    //! 
    //! Complexity: Logarithmic.
-   T& operator[](const key_type& k) 
-   {
-      //we can optimize this
-      iterator i = lower_bound(k);
-      // i->first is greater than or equivalent to k.
-      if (i == end() || key_comp()(k, (*i).first)){
-         containers_detail::value_init v;
-         value_type val(k, boost::move(v.m_t));
-         i = insert(i, boost::move(val));
-      }
-      return (*i).second;
-   }
+   mapped_type& operator[](const key_type &k);
 
    //! 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)
@@ -343,18 +346,10 @@ class map
    //! Returns: A reference to the mapped_type corresponding to x in *this.
    //! 
    //! Complexity: Logarithmic.
-   T& operator[](BOOST_RV_REF(key_type) mk) 
-   {
-      key_type &k = mk;
-      //we can optimize this
-      iterator i = lower_bound(k);
-      // i->first is greater than or equivalent to k.
-      if (i == end() || key_comp()(k, (*i).first)){
-         value_type val(boost::move(k), boost::move(T()));
-         i = insert(i, boost::move(val));
-      }
-      return (*i).second;
-   }
+   mapped_type& operator[](key_type &&k);
+   #else
+   BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, priv_subscript)
+   #endif
 
    //! Returns: A reference to the element whose key is equivalent to x.
    //! Throws: An exception object of type out_of_range if no such element is present.
@@ -508,7 +503,7 @@ class map
    void insert(InputIterator first, InputIterator last) 
    {  m_tree.insert_unique(first, last);  }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... in the container if and only if there is 
@@ -538,27 +533,23 @@ class map
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {  return m_tree.emplace_hint_unique(hint, boost::forward(args)...); }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
-   iterator emplace()
-   {  return m_tree.emplace_unique(); }
-
-   iterator emplace_hint(const_iterator hint)
-   {  return m_tree.emplace_hint_unique(hint); }
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                                       \
-   template                                                            \
-   iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                               \
-   {  return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }          \
-                                                                                                         \
-   template                                                            \
-   iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))     \
-   {  return m_tree.emplace_hint_unique(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));}\
+   #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_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, _));}  \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Erases the element pointed to by position.
    //!
@@ -660,7 +651,35 @@ class map
                            const map&);
    template 
    friend bool operator< (const map&,
-                           const map&);
+                          const map&);
+   private:
+   mapped_type& priv_subscript(const key_type &k)
+   {
+      //we can optimize this
+      iterator i = lower_bound(k);
+      // i->first is greater than or equivalent to k.
+      if (i == end() || key_comp()(k, (*i).first)){
+         container_detail::value_init m;
+         nonconst_impl_value_type val(k, boost::move(m.m_t));
+         i = insert(i, boost::move(val));
+      }
+      return (*i).second;
+   }
+
+   mapped_type& priv_subscript(BOOST_RV_REF(key_type) mk) 
+   {
+      key_type &k = mk;
+      //we can optimize this
+      iterator i = lower_bound(k);
+      // i->first is greater than or equivalent to k.
+      if (i == end() || key_comp()(k, (*i).first)){
+         container_detail::value_init m;
+         nonconst_impl_value_type val(boost::move(k), boost::move(m.m_t));
+         i = insert(i, boost::move(val));
+      }
+      return (*i).second;
+   }
+
    /// @endcond
 };
 
@@ -747,12 +766,14 @@ class multimap
    /// @cond
    private:
    BOOST_COPYABLE_AND_MOVABLE(multimap)
-   typedef containers_detail::rbtree, 
-                           containers_detail::select1st< std::pair >, 
+                           container_detail::select1st< std::pair >, 
                            Pred, 
                            A> tree_t;
    tree_t m_tree;  // red-black tree representing map
+   typedef typename container_detail::
+      move_const_ref_type::type insert_key_const_ref_type;
    /// @endcond
 
    public:
@@ -775,7 +796,7 @@ class multimap
    typedef typename tree_t::allocator_type         allocator_type;
    typedef typename tree_t::stored_allocator_type  stored_allocator_type;
    typedef std::pair        nonconst_value_type;
-   typedef containers_detail::pair
+   typedef container_detail::pair
                             nonconst_impl_value_type;
 
    /// @cond
@@ -794,16 +815,25 @@ class multimap
    /// @endcond
    typedef value_compare_impl                      value_compare;
 
+   //! Effects: Default constructs an empty multimap.
+   //! 
+   //! Complexity: Constant.
+   multimap()
+      : m_tree()
+   {
+      //Allocator type must be std::pair
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename A::value_type>::value));
+   }
+
    //! Effects: Constructs an empty multimap using the specified comparison
    //!   object and allocator.
    //! 
    //! Complexity: Constant.
-   explicit multimap(const Pred& comp = Pred(),
-                     const allocator_type& a = allocator_type())
+   explicit multimap(const Pred& comp, const allocator_type& a = allocator_type())
       : m_tree(comp, a)
    {
       //Allocator type must be std::pair
-      BOOST_STATIC_ASSERT((containers_detail::is_same, typename     A::value_type>::value));
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename     A::value_type>::value));
    }
 
    //! Effects: Constructs an empty multimap using the specified comparison object
@@ -818,7 +848,7 @@ class multimap
       : m_tree(first, last, comp, a, false) 
    {
       //Allocator type must be std::pair
-      BOOST_STATIC_ASSERT((containers_detail::is_same, typename     A::value_type>::value));
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename     A::value_type>::value));
    }
 
    //! Effects: Constructs an empty multimap using the specified comparison object and 
@@ -842,7 +872,7 @@ class multimap
       : m_tree(x.m_tree)
    {
       //Allocator type must be std::pair
-      BOOST_STATIC_ASSERT((containers_detail::is_same, typename     A::value_type>::value));
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename     A::value_type>::value));
    }
 
    //! Effects: Move constructs a multimap. Constructs *this using x's resources.
@@ -854,7 +884,7 @@ class multimap
       : m_tree(boost::move(x.m_tree))
    {
       //Allocator type must be std::pair
-      BOOST_STATIC_ASSERT((containers_detail::is_same, typename     A::value_type>::value));
+      BOOST_STATIC_ASSERT((container_detail::is_same, typename     A::value_type>::value));
    }
 
    //! Effects: Makes *this a copy of x.
@@ -1078,7 +1108,7 @@ class multimap
    void insert(InputIterator first, InputIterator last) 
    {  m_tree.insert_equal(first, last); }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... in the container.
@@ -1106,27 +1136,23 @@ class multimap
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {  return m_tree.emplace_hint_equal(hint, boost::forward(args)...); }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
-   iterator emplace()
-   {  return m_tree.emplace_equal(); }
-
-   iterator emplace_hint(const_iterator hint)
-   {  return m_tree.emplace_hint_equal(hint); }
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                                       \
-   template                                                            \
-   iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                               \
-   {  return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }           \
-                                                                                                         \
-   template                                                            \
-   iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))     \
-   {  return m_tree.emplace_hint_equal(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }\
+   #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 (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Erases the element pointed to by position.
    //!
@@ -1288,5 +1314,5 @@ namespace container {
 
 #include 
 
-#endif /* BOOST_CONTAINERS_MAP_HPP */
+#endif /* BOOST_CONTAINER_MAP_HPP */
 
diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp
index 8ea4e76..485f64d 100644
--- a/include/boost/container/set.hpp
+++ b/include/boost/container/set.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_SET_HPP
-#define BOOST_CONTAINERS_SET_HPP
+#ifndef BOOST_CONTAINER_SET_HPP
+#define BOOST_CONTAINER_SET_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -27,7 +27,7 @@
 #include 
 #include 
 #include 
-#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
+#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
 #include 
 #endif
 
@@ -67,10 +67,10 @@ class set
    /// @cond
    private:
    BOOST_COPYABLE_AND_MOVABLE(set)
-   typedef containers_detail::rbtree, Pred, A> tree_t;
+   typedef container_detail::rbtree, Pred, A> tree_t;
    tree_t m_tree;  // red-black tree representing set
-   typedef typename containers_detail::
+   typedef typename container_detail::
       move_const_ref_type::type insert_const_ref_type;
    /// @endcond
 
@@ -94,11 +94,18 @@ class set
    typedef typename tree_t::allocator_type         allocator_type;
    typedef typename tree_t::stored_allocator_type  stored_allocator_type;
 
+   //! Effects: Default constructs an empty set.
+   //! 
+   //! Complexity: Constant.
+   set()
+      : m_tree()
+   {}
+
    //! Effects: Constructs an empty set using the specified comparison object 
    //! and allocator.
    //! 
    //! Complexity: Constant.
-   explicit set(const Pred& comp = Pred(),
+   explicit set(const Pred& comp,
                 const allocator_type& a = allocator_type())
       : m_tree(comp, a)
    {}
@@ -334,7 +341,7 @@ class set
    { return this->insert(const_cast(x)); }
 
    template
-   std::pair insert(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   std::pair insert(const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return priv_insert(u); }
    #endif
 
@@ -366,7 +373,7 @@ class set
    { return this->insert(position, const_cast(x)); }
 
    template
-   iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return priv_insert(position, u); }
    #endif
 
@@ -389,7 +396,7 @@ class set
    void insert(InputIterator first, InputIterator last) 
    {  m_tree.insert_unique(first, last);  }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects:  Inserts an object of type T constructed with
    //!   std::forward(args)... if and only if there is 
@@ -418,27 +425,23 @@ class set
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {  return m_tree.emplace_hint_unique(hint, boost::forward(args)...); }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
-   iterator emplace()
-   {  return m_tree.emplace_unique(); }
-
-   iterator emplace_hint(const_iterator hint)
-   {  return m_tree.emplace_hint_unique(hint); }
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                                       \
-   template                                                            \
-   iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                               \
-   {  return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }          \
-                                                                                                         \
-   template                                                            \
-   iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))     \
-   {  return m_tree.emplace_hint_unique(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));}\
+   #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_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, _));}  \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Erases the element pointed to by p.
    //!
@@ -629,10 +632,10 @@ class multiset
    /// @cond
    private:
    BOOST_COPYABLE_AND_MOVABLE(multiset)
-   typedef containers_detail::rbtree, Pred, A> tree_t;
+   typedef container_detail::rbtree, Pred, A> tree_t;
    tree_t m_tree;  // red-black tree representing multiset
-   typedef typename containers_detail::
+   typedef typename container_detail::
       move_const_ref_type::type insert_const_ref_type;
    /// @endcond
 
@@ -660,7 +663,15 @@ class multiset
    //!   object and allocator.
    //! 
    //! Complexity: Constant.
-   explicit multiset(const Pred& comp = Pred(),
+   multiset()
+      : m_tree()
+   {}
+
+   //! Effects: Constructs an empty multiset using the specified comparison
+   //!   object and allocator.
+   //! 
+   //! Complexity: Constant.
+   explicit multiset(const Pred& comp,
                      const allocator_type& a = allocator_type())
       : m_tree(comp, a)
    {}
@@ -893,7 +904,7 @@ class multiset
    { return this->insert(const_cast(x)); }
 
    template
-   iterator insert(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   iterator insert(const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return priv_insert(u); }
    #endif
 
@@ -923,7 +934,7 @@ class multiset
    { return this->insert(position, const_cast(x)); }
 
    template
-   iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return priv_insert(position, u); }
    #endif
 
@@ -947,7 +958,7 @@ class multiset
    void insert(InputIterator first, InputIterator last) 
    {  m_tree.insert_equal(first, last);  }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... and returns the iterator pointing to the
@@ -970,27 +981,23 @@ class multiset
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {  return m_tree.emplace_hint_equal(hint, boost::forward(args)...); }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
-   iterator emplace()
-   {  return m_tree.emplace_equal(); }
-
-   iterator emplace_hint(const_iterator hint)
-   {  return m_tree.emplace_hint_equal(hint); }
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                                       \
-   template                                                            \
-   iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                               \
-   {  return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }           \
-                                                                                                         \
-   template                                                            \
-   iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))     \
-   {  return m_tree.emplace_hint_equal(hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); }\
+   #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 (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Erases the element pointed to by p.
    //!
@@ -1159,5 +1166,5 @@ namespace container {
 
 #include 
 
-#endif /* BOOST_CONTAINERS_SET_HPP */
+#endif /* BOOST_CONTAINER_SET_HPP */
 
diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp
index d5121a0..ffa538e 100644
--- a/include/boost/container/slist.hpp
+++ b/include/boost/container/slist.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_SLIST_HPP
-#define BOOST_CONTAINERS_SLIST_HPP
+#ifndef BOOST_CONTAINER_SLIST_HPP
+#define BOOST_CONTAINER_SLIST_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -20,7 +20,7 @@
 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -29,7 +29,7 @@
 #include 
 
 
-#if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 //Preprocessor library to emulate perfect forwarding
 #else
 #include  
@@ -52,46 +52,43 @@ namespace container {
 
 /// @cond
 
-namespace containers_detail {
+namespace container_detail {
 
 template
 struct slist_hook
 {
-   typedef typename containers_detail::bi::make_slist_base_hook
-      , containers_detail::bi::link_mode >::type type;
+   typedef typename container_detail::bi::make_slist_base_hook
+      , container_detail::bi::link_mode >::type type;
 };
 
 template 
 struct slist_node
    :  public slist_hook::type
 {
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    slist_node()
       : m_data()
    {}
 
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
    template
    slist_node(Args &&...args)
       : m_data(boost::forward(args)...)
    {}
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
-   slist_node()
-      : m_data()
-   {}
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                                           \
-   template                                                \
-   slist_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                         \
-      : m_data(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))                     \
-   {}                                                                                        \
+   #define BOOST_PP_LOCAL_MACRO(n)                                      \
+   template                           \
+   slist_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))       \
+      : m_data(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))   \
+   {}                                                                   \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif//#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif//#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    T m_data;
 };
@@ -99,22 +96,26 @@ struct slist_node
 template
 struct intrusive_slist_type
 {
-   typedef typename A::value_type               value_type;
-   typedef typename boost::pointer_to_other
-      ::type         void_pointer;
-   typedef typename containers_detail::slist_node
+   typedef boost::container::allocator_traits      allocator_traits_type;
+   typedef typename allocator_traits_type::value_type value_type;
+   typedef typename boost::intrusive::pointer_traits
+      ::template
+         rebind_pointer::type
+            void_pointer;
+   typedef typename container_detail::slist_node
                       node_type;
 
-   typedef typename containers_detail::bi::make_slist
+   typedef typename container_detail::bi::make_slist
       ::type>
-      ,containers_detail::bi::constant_time_size
-      ,containers_detail::bi::size_type
+      ,container_detail::bi::base_hook::type>
+      ,container_detail::bi::constant_time_size
+      , container_detail::bi::size_type
+         
       >::type                                   container_type;
    typedef container_type                       type ;
 };
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 
 /// @endcond
 
@@ -156,24 +157,25 @@ template  >
 template 
 #endif
 class slist 
-   : protected containers_detail::node_alloc_holder
-      ::type>
+   : protected container_detail::node_alloc_holder
+      ::type>
 {
    /// @cond
-   typedef typename containers_detail::
+   typedef typename container_detail::
       move_const_ref_type::type                    insert_const_ref_type;
    typedef typename 
-      containers_detail::intrusive_slist_type::type           Icont;
-   typedef containers_detail::node_alloc_holder        AllocHolder;
+      container_detail::intrusive_slist_type::type           Icont;
+   typedef container_detail::node_alloc_holder        AllocHolder;
    typedef typename AllocHolder::NodePtr              NodePtr;
    typedef slist                                ThisType;
    typedef typename AllocHolder::NodeAlloc            NodeAlloc;
    typedef typename AllocHolder::ValAlloc             ValAlloc;
    typedef typename AllocHolder::Node                 Node;
-   typedef containers_detail::allocator_destroyer     Destroyer;
+   typedef container_detail::allocator_destroyer     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_traits_type;
 
    class equal_to_value
    {
@@ -206,23 +208,23 @@ class slist
    /// @endcond
    public:
    //! The type of object, T, stored in the list
-   typedef T                                       value_type;
+   typedef T                                                value_type;
    //! Pointer to T
-   typedef typename A::pointer                     pointer;
+   typedef typename allocator_traits_type::pointer          pointer;
    //! Const pointer to T
-   typedef typename A::const_pointer               const_pointer;
+   typedef typename allocator_traits_type::const_pointer    const_pointer;
    //! Reference to T
-   typedef typename A::reference                   reference;
+   typedef typename allocator_traits_type::reference        reference;
    //! Const reference to T
-   typedef typename A::const_reference             const_reference;
+   typedef typename allocator_traits_type::const_reference  const_reference;
    //! An unsigned integral type
-   typedef typename A::size_type                   size_type;
+   typedef typename allocator_traits_type::size_type        size_type;
    //! A signed integral type
-   typedef typename A::difference_type             difference_type;
+   typedef typename allocator_traits_type::difference_type  difference_type;
    //! The allocator type
-   typedef A                                       allocator_type;
-   //! The stored allocator type
-   typedef NodeAlloc                               stored_allocator_type;
+   typedef A                                                allocator_type;
+   //! Non-standard extension: the stored allocator type
+   typedef NodeAlloc                                        stored_allocator_type;
 
    /// @cond
    private:
@@ -328,7 +330,16 @@ class slist
    //! Throws: If allocator_type's copy constructor throws.
    //! 
    //! Complexity: Constant.
-   explicit slist(const allocator_type& a = allocator_type())
+   slist()
+      :  AllocHolder()
+   {}
+
+   //! Effects: Constructs a list taking the allocator as parameter.
+   //! 
+   //! Throws: If allocator_type's copy constructor throws.
+   //! 
+   //! Complexity: Constant.
+   explicit slist(const allocator_type& a)
       :  AllocHolder(a)
    {}
 
@@ -377,7 +388,7 @@ class slist
    //! 
    //! Complexity: Constant.
    slist(BOOST_RV_REF(slist) x)
-      : AllocHolder(boost::move((AllocHolder&)x))
+      : AllocHolder(boost::move(static_cast(x)))
    {}
 
    //! Effects: Makes *this contain the same elements as x.
@@ -391,6 +402,14 @@ class slist
    slist& operator= (BOOST_COPY_ASSIGN_REF(slist) x)
    {
       if (&x != this){
+         NodeAlloc &this_alloc     = this->node_alloc();
+         const NodeAlloc &x_alloc  = x.node_alloc();
+         container_detail::bool_ flag;
+         if(flag && this_alloc != x_alloc){
+            this->clear();
+         }
+         this->AllocHolder::copy_assign_alloc(x);
          this->assign(x.begin(), x.end());
       }
       return *this;
@@ -404,11 +423,25 @@ class slist
    //! Throws: If memory allocation throws or T's copy constructor throws.
    //!
    //! Complexity: Linear to the number of elements in x.
-   slist& operator= (BOOST_RV_REF(slist) mx)
+   slist& operator= (BOOST_RV_REF(slist) x)
    {
-      if (&mx != this){
-         this->clear();
-         this->swap(mx);
+      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_category ItCat;
+            this->assign( boost::make_move_iterator(x.begin())
+                        , boost::make_move_iterator(x.end()));
+         }
       }
       return *this;
    }
@@ -455,8 +488,8 @@ class slist
    template 
    void assign(InpIt first, InpIt last) 
    {
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_assign_dispatch(first, last, Result());
    }
 
@@ -607,7 +640,7 @@ class slist
    void push_front(T &x) { push_front(const_cast(x)); }
 
    template
-   void push_front(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   void push_front(const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return priv_push_front(u); }
    #endif
 
@@ -669,7 +702,7 @@ class slist
    { return this->insert_after(position, const_cast(x)); }
 
    template
-   iterator insert_after(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   iterator insert_after(const_iterator position, const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return this->priv_insert_after(position, u); }
    #endif
 
@@ -717,8 +750,8 @@ class slist
    template 
    void insert_after(const_iterator prev_pos, InIter first, InIter last) 
    {
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_insert_after_range_dispatch(prev_pos, first, last, Result());
    }
 
@@ -737,7 +770,7 @@ class slist
    { return this->insert(position, const_cast(x)); }
 
    template
-   iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return this->priv_insert(position, u); }
    #endif
 
@@ -774,7 +807,7 @@ class slist
    void insert(const_iterator p, InIter first, InIter last) 
    {  return this->insert_after(previous(p), first, last); }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... in the front of the list
@@ -808,63 +841,42 @@ class slist
    template 
    iterator emplace_after(const_iterator prev, Args&&... args)
    {
-      typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator());
-      new ((void*)containers_detail::get_pointer(d.get())) Node(boost::forward(args)...);
-      NodePtr node = d.get();
-      d.release();
-      return iterator(this->icont().insert_after(prev.get(), *node));
+      NodePtr pnode(AllocHolder::create_node(boost::forward(args)...));
+      return iterator(this->icont().insert_after(prev.get(), *pnode));
    }
 
-   #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
-
-   //0 args
-   void emplace_front()
-   {  this->emplace_after(this->cbefore_begin());   }
-
-   iterator emplace(const_iterator p)
-   {  return this->emplace_after(this->previous(p));  }
-
-   iterator emplace_after(const_iterator prev)
-   {
-      typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator());
-      new ((void*)containers_detail::get_pointer(d.get())) Node();
-      NodePtr node = d.get();
-      d.release();
-      return iterator(this->icont().insert_after(prev.get(), *node));
-   }
+   #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    #define BOOST_PP_LOCAL_MACRO(n)                                                           \
-   template                                                \
-   void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINERS_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, _))                    \
    {                                                                                         \
-      this->emplace                                                                          \
-         (this->cbegin(), BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));         \
+      this->emplace(this->cbegin()                                                           \
+          BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));                   \
    }                                                                                         \
                                                                                              \
-   template                                                \
-   iterator emplace                                                                          \
-      (const_iterator p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))              \
+   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(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));      \
+         (this->previous(p)                                                                  \
+          BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));                   \
    }                                                                                         \
                                                                                              \
-   template                                                \
-   iterator emplace_after                                                                    \
-      (const_iterator prev, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))           \
+   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, _))                \
    {                                                                                         \
-      typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator());       \
-      new ((void*)containers_detail::get_pointer(d.get()))                                              \
-         Node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                     \
-      NodePtr node = d.get();                                                                \
-      d.release();                                                                           \
-      return iterator(this->icont().insert_after(prev.get(), *node));                        \
+      NodePtr pnode (AllocHolder::create_node                                                \
+         (BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)));                           \
+      return iterator(this->icont().insert_after(prev.get(), *pnode));                       \
    }                                                                                         \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Erases the element after the element pointed by prev_pos
    //!    of the list.
@@ -1337,11 +1349,11 @@ class slist
    template 
    void priv_insert_dispatch(const_iterator prev,
                              InputIter first, InputIter last,
-                             containers_detail::false_)
+                             container_detail::false_)
    {  this->priv_create_and_insert_nodes(prev, first, last);   }
 
    template
-   void priv_insert_dispatch(const_iterator prev, Integer n, Integer x, containers_detail::true_) 
+   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);  }
 
    void priv_fill_assign(size_type n, const T& val) 
@@ -1361,11 +1373,11 @@ class slist
    }
 
    template 
-   void priv_assign_dispatch(Int n, Int val, containers_detail::true_)
+   void priv_assign_dispatch(Int n, Int val, container_detail::true_)
    {  this->priv_fill_assign((size_type) n, (T)val); }
 
    template 
-   void priv_assign_dispatch(InpIt first, InpIt last, containers_detail::false_)
+   void priv_assign_dispatch(InpIt first, InpIt last, container_detail::false_)
    {
       iterator end_n(this->end());
       iterator prev(this->before_begin());
@@ -1383,11 +1395,11 @@ class slist
    }
 
    template 
-   void priv_insert_after_range_dispatch(const_iterator prev_pos, Int n, Int x, containers_detail::true_) 
+   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);  }
 
    template 
-   void priv_insert_after_range_dispatch(const_iterator prev_pos, InIter first, InIter last, containers_detail::false_) 
+   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); }
 
    //Functors for member algorithm defaults
@@ -1533,4 +1545,4 @@ class insert_iterator >
 
 #include 
 
-#endif /* BOOST_CONTAINERS_SLIST_HPP */
+#endif /* BOOST_CONTAINER_SLIST_HPP */
diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp
index 1886e29..2d25fbe 100644
--- a/include/boost/container/stable_vector.hpp
+++ b/include/boost/container/stable_vector.hpp
@@ -27,15 +27,14 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
+#include 
 
 #include 
 #include 
@@ -79,7 +78,7 @@ struct smart_ptr_type
 };
 
 template
-inline typename smart_ptr_type::pointer get_pointer(const Ptr &ptr)
+inline typename smart_ptr_type::pointer to_raw_pointer(const Ptr &ptr)
 {  return smart_ptr_type::get(ptr);   }
 
 template 
@@ -126,33 +125,29 @@ template
 struct node_type
    : public node_type_base
 {
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
-
    node_type()
       : value()
    {}
 
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
    template
    node_type(Args &&...args)
       : value(boost::forward(args)...)
    {}
 
-   #else //BOOST_CONTAINERS_PERFECT_FORWARDING
+   #else //BOOST_CONTAINER_PERFECT_FORWARDING
 
-   node_type()
-      : value()
-   {}
-
-   #define BOOST_PP_LOCAL_MACRO(n)                                      \
-   template                           \
-   node_type(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))       \
-      : value(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))   \
-   {}                                                                   \
+   #define BOOST_PP_LOCAL_MACRO(n)                                                           \
+   BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >)    \
+   node_type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                            \
+      : value(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))                        \
+   {}                                                                                        \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif//BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif//BOOST_CONTAINER_PERFECT_FORWARDING
    
    void set_pointer(VoidPointer p)
    {  node_type_base::set_pointer(p); }
@@ -163,33 +158,38 @@ struct node_type
 template
 class iterator
    : public std::iterator< std::random_access_iterator_tag
-                         , typename std::iterator_traits::value_type
-                         , typename std::iterator_traits::difference_type
+                         , T
+                         , typename boost::intrusive::
+                              pointer_traits::difference_type
                          , Pointer
                          , Reference>
 {
+   typedef typename boost::intrusive::
+      pointer_traits::template
+         rebind_pointer::type                void_ptr;
+   typedef typename boost::intrusive::
+      pointer_traits::template
+         rebind_pointer::type          const_void_ptr;
+   typedef node_type                  node_type_t;
+   typedef typename boost::intrusive::
+      pointer_traits::template
+         rebind_pointer::type         node_type_ptr_t;
+   typedef typename boost::intrusive::
+      pointer_traits::template
+         rebind_pointer::type   const_node_type_ptr_t;
+   typedef typename boost::intrusive::
+      pointer_traits::template
+         rebind_pointer::type            void_ptr_ptr;
 
-   typedef typename boost::pointer_to_other
-      ::type                  void_ptr;
-   typedef typename boost::pointer_to_other
-      ::type            const_void_ptr;
-   typedef node_type            node_type_t;
-   typedef typename boost::pointer_to_other
-      ::type          node_type_ptr_t;
-   typedef typename boost::pointer_to_other
-      ::type    const_node_type_ptr_t;
-   typedef typename boost::pointer_to_other
-      ::type             void_ptr_ptr;
-
-   friend class iterator::type>;
+   friend class iterator::template rebind_pointer::type>;
 
    public:
-   typedef std::random_access_iterator_tag   iterator_category;
-   typedef T                                 value_type;
-   typedef typename std::iterator_traits
-      ::difference_type             difference_type;
-   typedef Pointer                           pointer;
-   typedef Reference                         reference;
+   typedef std::random_access_iterator_tag      iterator_category;
+   typedef T                                    value_type;
+   typedef typename boost::intrusive::
+      pointer_traits::difference_type  difference_type;
+   typedef Pointer                              pointer;
+   typedef Reference                            reference;
 
    iterator()
    {}
@@ -198,27 +198,24 @@ class iterator
       : pn(pn)
    {}
 
-   iterator(const iterator::type >& x)
+   iterator(const iterator::template rebind_pointer::type>& x)
       : pn(x.pn)
    {}
    
    private:
    static node_type_ptr_t node_ptr_cast(const void_ptr &p)
    {
-      using boost::get_pointer;
-      return node_type_ptr_t(static_cast(stable_vector_detail::get_pointer(p)));
+      return node_type_ptr_t(static_cast(stable_vector_detail::to_raw_pointer(p)));
    }
 
    static const_node_type_ptr_t node_ptr_cast(const const_void_ptr &p)
    {
-      using boost::get_pointer;
-      return const_node_type_ptr_t(static_cast(stable_vector_detail::get_pointer(p)));
+      return const_node_type_ptr_t(static_cast(stable_vector_detail::to_raw_pointer(p)));
    }
 
    static void_ptr_ptr void_ptr_ptr_cast(const void_ptr &p)
    {
-      using boost::get_pointer;
-      return void_ptr_ptr(static_cast(stable_vector_detail::get_pointer(p)));
+      return void_ptr_ptr(static_cast(stable_vector_detail::to_raw_pointer(p)));
    }
 
    reference dereference() const
@@ -325,12 +322,15 @@ struct select_multiallocation_chain
 template
 struct select_multiallocation_chain
 {
-   typedef typename A::template
-      rebind::other::pointer                          void_ptr;
-   typedef containers_detail::basic_multiallocation_chain
+   typedef typename boost::intrusive::pointer_traits
+      ::pointer>::
+         template rebind_pointer::type                void_ptr;
+   typedef container_detail::basic_multiallocation_chain
                                                   multialloc_cached_counted;
-   typedef boost::container::containers_detail::transform_multiallocation_chain
-         type;
+   typedef boost::container::container_detail::
+      transform_multiallocation_chain
+         < multialloc_cached_counted
+         , typename allocator_traits::value_type>        type;
 };
 
 } //namespace stable_vector_detail
@@ -389,59 +389,82 @@ template 
 class stable_vector
 {
    ///@cond
-   typedef typename containers_detail::
-      move_const_ref_type::type insert_const_ref_type;
-   typedef typename A::template
-      rebind::other::pointer                    void_ptr;
-   typedef typename boost::pointer_to_other
-      ::type                    const_void_ptr;
-   typedef typename A::template
-      rebind::other::pointer                void_ptr_ptr;
-   typedef typename boost::pointer_to_other
-      ::type                const_void_ptr_ptr;
+   typedef allocator_traits                        allocator_traits_type;
+   typedef typename container_detail::
+      move_const_ref_type::type                    insert_const_ref_type;
+   typedef typename boost::intrusive::pointer_traits
+      ::
+         template rebind_pointer::type          void_ptr;
+   typedef typename boost::intrusive::pointer_traits
+      ::template
+         rebind_pointer::type             const_void_ptr;
+   typedef typename boost::intrusive::pointer_traits
+      ::template
+         rebind_pointer::type               void_ptr_ptr;
+   typedef typename boost::intrusive::pointer_traits
+      ::template
+         rebind_pointer::type         const_void_ptr_ptr;
    typedef stable_vector_detail::node_type
                                          node_type_t;
-   typedef typename A::template
-      rebind::other::pointer             node_type_ptr_t;
+   typedef typename boost::intrusive::pointer_traits
+      ::template
+         rebind_pointer::type            node_type_ptr_t;
    typedef stable_vector_detail::node_type_base
                                             node_type_base_t;
-   typedef typename A::template
-      rebind::other::pointer        node_type_base_ptr_t;
-   typedef 
-   ::boost::container::vector::other
-   >                                                  impl_type;
+   typedef typename boost::intrusive::pointer_traits
+      ::template
+         rebind_pointer::type       node_type_base_ptr_t;
+   typedef ::boost::container::vector::type>                         impl_type;
    typedef typename impl_type::iterator               impl_iterator;
    typedef typename impl_type::const_iterator         const_impl_iterator;
 
-   typedef ::boost::container::containers_detail::
+   typedef ::boost::container::container_detail::
       integral_constant                  allocator_v1;
-   typedef ::boost::container::containers_detail::
+   typedef ::boost::container::container_detail::
       integral_constant                  allocator_v2;
-   typedef ::boost::container::containers_detail::integral_constant 
-      ::value>                      alloc_version;
-   typedef typename A::
-      template rebind::other             node_allocator_type;
+   typedef ::boost::container::container_detail::integral_constant 
+      ::value>                              alloc_version;
+   typedef typename allocator_traits_type::
+      template portable_rebind_alloc
+         ::type                          node_allocator_type;
 
    node_type_ptr_t allocate_one()
    {  return this->allocate_one(alloc_version());   }
 
-   node_type_ptr_t allocate_one(allocator_v1)
-   {  return get_al().allocate(1);   }
+   template
+   node_type_ptr_t allocate_one(AllocatorVersion,
+      typename boost::container::container_detail::enable_if_c
+         
+            ::value>::type * = 0)
+   {  return node_alloc().allocate(1);   }
 
-   node_type_ptr_t allocate_one(allocator_v2)
-   {  return get_al().allocate_one();   }
+   template
+   node_type_ptr_t allocate_one(AllocatorVersion,
+      typename boost::container::container_detail::enable_if_c
+         
+            ::value>::type * = 0)
+   {  return node_alloc().allocate_one();   }
 
    void deallocate_one(node_type_ptr_t p)
    {  return this->deallocate_one(p, alloc_version());   }
 
-   void deallocate_one(node_type_ptr_t p, allocator_v1)
-   {  get_al().deallocate(p, 1);   }
+   template
+   void deallocate_one(node_type_ptr_t p, AllocatorVersion,
+      typename boost::container::container_detail::enable_if_c
+         
+            ::value>::type * = 0)
+   {  node_alloc().deallocate(p, 1);   }
 
-   void deallocate_one(node_type_ptr_t p, allocator_v2)
-   {  get_al().deallocate_one(p);   }
+   template
+   void deallocate_one(node_type_ptr_t p, AllocatorVersion,
+      typename boost::container::container_detail::enable_if_c
+         
+            ::value>::type * = 0)
+   {  node_alloc().deallocate_one(p);   }
 
    friend class stable_vector_detail::clear_on_destroy;
    ///@endcond
@@ -450,10 +473,10 @@ class stable_vector
 
    // types:
 
-   typedef typename A::reference              reference;
-   typedef typename A::const_reference        const_reference;
-   typedef typename A::pointer                pointer;
-   typedef typename A::const_pointer          const_pointer;
+   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
                                        iterator;
    typedef stable_vector_detail::iterator
@@ -461,9 +484,10 @@ class stable_vector
    typedef typename impl_type::size_type              size_type;
    typedef typename iterator::difference_type         difference_type;
    typedef T                                          value_type;
-   typedef A                                  allocator_type;
+   typedef A                                          allocator_type;
    typedef std::reverse_iterator            reverse_iterator;
    typedef std::reverse_iterator      const_reverse_iterator;
+   typedef node_allocator_type                        stored_allocator_type;
 
    ///@cond
    private:
@@ -483,13 +507,24 @@ class stable_vector
    ///@endcond
    public:
 
+   //! Effects: Default constructs a stable_vector.
+   //! 
+   //! Throws: If allocator_type's default constructor throws.
+   //! 
+   //! Complexity: Constant.
+   stable_vector()
+      : internal_data(), impl()
+   {
+      STABLE_VECTOR_CHECK_INVARIANT;
+   }
+
    //! Effects: Constructs a stable_vector taking the allocator as parameter.
    //! 
    //! Throws: If allocator_type's copy constructor throws.
    //! 
    //! Complexity: Constant.
-   explicit stable_vector(const A& al=A())
-   : internal_data(al),impl(al)
+   explicit stable_vector(const A& al)
+      : internal_data(al),impl(al)
    {
       STABLE_VECTOR_CHECK_INVARIANT;
    }
@@ -502,7 +537,7 @@ class stable_vector
    //! 
    //! Complexity: Linear to n.
    explicit stable_vector(size_type n)
-   : internal_data(A()),impl(A())
+      : internal_data(A()),impl(A())
    {
       stable_vector_detail::clear_on_destroy cod(*this);
       this->resize(n);
@@ -518,7 +553,7 @@ class stable_vector
    //! 
    //! Complexity: Linear to n.
    stable_vector(size_type n, const T& t, const A& al=A())
-   : internal_data(al),impl(al)
+      : internal_data(al),impl(al)
    {
       stable_vector_detail::clear_on_destroy cod(*this);
       this->insert(this->cbegin(), n, t);
@@ -549,7 +584,10 @@ class stable_vector
    //! 
    //! Complexity: Linear to the elements x contains.
    stable_vector(const stable_vector& x)
-      : internal_data(x.get_al()),impl(x.get_al())
+      : internal_data(allocator_traits::
+         select_on_container_copy_construction(x.node_alloc()))
+      , impl(allocator_traits::
+         select_on_container_copy_construction(x.impl.get_stored_allocator()))
    {
       stable_vector_detail::clear_on_destroy cod(*this);
       this->insert(this->cbegin(), x.begin(), x.end());
@@ -562,9 +600,11 @@ class stable_vector
    //! Throws: If allocator_type's copy constructor throws.
    //! 
    //! Complexity: Constant.
-   stable_vector(BOOST_RV_REF(stable_vector) x) 
-      : internal_data(x.get_al()),impl(x.get_al())
-   {  this->swap(x);   }
+   stable_vector(BOOST_RV_REF(stable_vector) x)
+      : internal_data(boost::move(x.node_alloc())), impl(boost::move(x.impl))
+   {
+      this->priv_swap_members(x);
+   }
 
    //! Effects: Destroys the stable_vector. All stored values are destroyed
    //!   and used memory is deallocated.
@@ -589,7 +629,17 @@ class stable_vector
    stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
    {
       STABLE_VECTOR_CHECK_INVARIANT;
-      if (this != &x) {
+      if (&x != this){
+         node_allocator_type &this_alloc     = this->node_alloc();
+         const node_allocator_type &x_alloc  = x.node_alloc();
+         container_detail::bool_ 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);
          this->assign(x.begin(), x.end());
       }
       return *this;
@@ -606,8 +656,25 @@ class stable_vector
    stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
    {
       if (&x != this){
-         this->swap(x);
-         x.clear();
+         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_ 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_category ItCat;
+            this->assign( boost::make_move_iterator(x.begin())
+                        , boost::make_move_iterator(x.end()));
+         }
       }
       return *this;
    }
@@ -641,7 +708,27 @@ class stable_vector
    //! Throws: If allocator's copy constructor throws.
    //! 
    //! Complexity: Constant.
-   allocator_type get_allocator()const  {return get_al();}
+   allocator_type get_allocator()const  {return node_alloc();}
+
+   //! Effects: Returns a reference to the internal allocator.
+   //! 
+   //! Throws: Nothing
+   //! 
+   //! Complexity: Constant.
+   //! 
+   //! Note: Non-standard extension.
+   const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
+   {  return node_alloc(); }
+
+   //! Effects: Returns a reference to the internal allocator.
+   //! 
+   //! Throws: Nothing
+   //! 
+   //! Complexity: Constant.
+   //! 
+   //! Note: Non-standard extension.
+   stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
+   {  return node_alloc(); }
 
 
    //! Effects: Returns an iterator to the first element contained in the stable_vector.
@@ -946,7 +1033,8 @@ class stable_vector
    void push_back(T &x) { push_back(const_cast(x)); }
 
    template
-   void push_back(const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   void push_back(const U &u, typename container_detail::enable_if_c
+                  ::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    { return priv_push_back(u); }
    #endif
 
@@ -982,7 +1070,8 @@ class stable_vector
    iterator insert(const_iterator position, T &x) { return this->insert(position, const_cast(x)); }
 
    template
-   iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c::value && !::boost::has_move_emulation_enabled::value >::type* =0)
+   iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c
+                  ::value && !::boost::has_move_emulation_enabled::value >::type* =0)
    {  return this->priv_insert(position, u); }
    #endif
 
@@ -1035,7 +1124,7 @@ class stable_vector
                         boost::mpl::not_ >());
    }
 
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
 
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... in the end of the stable_vector.
@@ -1046,7 +1135,7 @@ class stable_vector
    template
    void emplace_back(Args &&...args)
    {
-      typedef emplace_functor         EmplaceFunctor;
+      typedef emplace_functor         EmplaceFunctor;
       typedef emplace_iterator EmplaceIterator;
       EmplaceFunctor &&ef = EmplaceFunctor(boost::forward(args)...);
       this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
@@ -1066,7 +1155,7 @@ class stable_vector
    {
       //Just call more general insert(pos, size, value) and return iterator
       size_type pos_n = position - cbegin();
-      typedef emplace_functor         EmplaceFunctor;
+      typedef emplace_functor         EmplaceFunctor;
       typedef emplace_iterator EmplaceIterator;
       EmplaceFunctor &&ef = EmplaceFunctor(boost::forward(args)...);
       this->insert(position, EmplaceIterator(ef), EmplaceIterator());
@@ -1075,51 +1164,40 @@ class stable_vector
 
    #else
 
-   void emplace_back()
-   {
-      typedef emplace_functor                   EmplaceFunctor;
-      typedef emplace_iterator  EmplaceIterator;
-      EmplaceFunctor ef;
-      this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
-   }
-
-   iterator emplace(const_iterator position)
-   {
-      typedef emplace_functor                   EmplaceFunctor;
-      typedef emplace_iterator  EmplaceIterator;
-      EmplaceFunctor ef;
-      size_type pos_n = position - this->cbegin();
-      this->insert(position, EmplaceIterator(ef), EmplaceIterator());
-      return iterator(this->begin() + pos_n);
-   }
-
    #define BOOST_PP_LOCAL_MACRO(n)                                                              \
-   template                                                   \
-   void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_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, _))                        \
    {                                                                                            \
       typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg)                               \
-                    EmplaceFunctor;                    \
+         BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >)               \
+            EmplaceFunctor;                                                                     \
       typedef emplace_iterator  EmplaceIterator;  \
-      EmplaceFunctor ef(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                \
-      this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());                       \
+      EmplaceFunctor ef BOOST_PP_LPAREN_IF(n)                                                   \
+                        BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)                   \
+                        BOOST_PP_RPAREN_IF(n);                                                  \
+      this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator());                      \
    }                                                                                            \
                                                                                                 \
-   template                                                   \
-   iterator emplace(const_iterator pos, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))    \
+   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 BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg)                               \
-                    EmplaceFunctor;                    \
+         BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >)               \
+            EmplaceFunctor;                                                                     \
       typedef emplace_iterator  EmplaceIterator;  \
-      EmplaceFunctor ef(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                \
+      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());                                \
       return iterator(this->begin() + pos_n);                                                   \
    }                                                                                            \
    //!
-   #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
 
    //! Effects: Erases the element at position pos.
    //!
@@ -1157,7 +1235,11 @@ class stable_vector
    void swap(stable_vector & x)
    {
       STABLE_VECTOR_CHECK_INVARIANT;
-      this->swap_impl(*this,x);
+      container_detail::bool_ flag;
+      container_detail::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
+      //vector's allocator is swapped here
+      this->impl.swap(x.impl);
+      this->priv_swap_members(x);
    }
 
    //! Effects: Erases all the elements of the stable_vector.
@@ -1181,7 +1263,8 @@ class stable_vector
          this->clear_pool();
          //If empty completely destroy the index, let's recover default-constructed state
          if(this->empty()){
-            impl_type().swap(this->impl);
+            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
@@ -1209,7 +1292,11 @@ class stable_vector
    void priv_push_back(const value_type &t)
    {  this->insert(end(), t);  }
 
-   void clear_pool(allocator_v1)
+   template
+   void clear_pool(AllocatorVersion,
+      typename boost::container::container_detail::enable_if_c
+         
+            ::value>::type * = 0)
    {
       if(!impl.empty() && impl.back()){
          void_ptr &pool_first_ref = impl.end()[-2];
@@ -1227,15 +1314,18 @@ class stable_vector
       }
    }
 
-   void clear_pool(allocator_v2)
+   template
+   void clear_pool(AllocatorVersion,
+      typename boost::container::container_detail::enable_if_c
+         
+            ::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);
-         get_al().deallocate_individual(boost::move(holder));
+         node_alloc().deallocate_individual(boost::move(holder));
          pool_first_ref = pool_last_ref = 0;
          this->internal_data.pool_size = 0;
       }
@@ -1251,7 +1341,11 @@ class stable_vector
       this->add_to_pool(n, alloc_version());
    }
 
-   void add_to_pool(size_type n, allocator_v1)
+   template
+   void add_to_pool(size_type n, AllocatorVersion,
+      typename boost::container::container_detail::enable_if_c
+         
+            ::value>::type * = 0)
    {
       size_type remaining = n;
       while(remaining--){
@@ -1259,14 +1353,18 @@ class stable_vector
       }
    }
 
-   void add_to_pool(size_type n, allocator_v2)
+   template
+   void add_to_pool(size_type n, AllocatorVersion,
+      typename boost::container::container_detail::enable_if_c
+         
+            ::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::value == true));
-      multiallocation_chain m (get_al().allocate_individual(n));
+      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 data(holder.extract_data());
@@ -1375,8 +1473,8 @@ class stable_vector
 
    template
    iterator priv_erase(const_iterator first, const_iterator last, AllocatorVersion,
-      typename boost::container::containers_detail::enable_if_c
-         
+      typename boost::container::container_detail::enable_if_c
+         
             ::value>::type * = 0)
    {
       STABLE_VECTOR_CHECK_INVARIANT;
@@ -1385,14 +1483,12 @@ class stable_vector
 
    static node_type_ptr_t node_ptr_cast(const void_ptr &p)
    {
-      using boost::get_pointer;
-      return node_type_ptr_t(static_cast(stable_vector_detail::get_pointer(p)));
+      return node_type_ptr_t(static_cast(stable_vector_detail::to_raw_pointer(p)));
    }
 
    static node_type_base_ptr_t node_base_ptr_cast(const void_ptr &p)
    {
-      using boost::get_pointer;
-      return node_type_base_ptr_t(static_cast(stable_vector_detail::get_pointer(p)));
+      return node_type_base_ptr_t(static_cast(stable_vector_detail::to_raw_pointer(p)));
    }
 
    static value_type& value(const void_ptr &p)
@@ -1434,7 +1530,7 @@ class stable_vector
    {
       node_type_ptr_t p = this->allocate_one();
       try{
-         boost::container::construct_in_place(&*p, it);
+         boost::container::construct_in_place(this->node_alloc(), &*p, it);
          p->set_pointer(up);
       }
       catch(...){
@@ -1516,7 +1612,7 @@ class stable_vector
    template 
    void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v2)
    {
-      multiallocation_chain mem(get_al().allocate_individual(n));
+      multiallocation_chain mem(node_alloc().allocate_individual(n));
 
       size_type i = 0;
       node_type_ptr_t p = 0;
@@ -1525,7 +1621,7 @@ class stable_vector
             p = mem.front();
             mem.pop_front();
             //This can throw
-            boost::container::construct_in_place(&*p, first);
+            boost::container::construct_in_place(this->node_alloc(), &*p, first);
             p->set_pointer(void_ptr_ptr(&it[i]));
             ++first;
             it[i] = p;
@@ -1533,8 +1629,8 @@ class stable_vector
          }
       }
       catch(...){
-         get_al().deallocate_one(p);
-         get_al().deallocate_many(boost::move(mem));
+         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;
@@ -1548,13 +1644,13 @@ class stable_vector
       node_type_ptr_t p = 0;
       try{
          while(first != last){
-            p = get_from_pool();
+            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(&*p, first);
+            boost::container::construct_in_place(this->node_alloc(), &*p, first);
             p->set_pointer(void_ptr_ptr(&it[i]));
             ++first;
             it[i]=p;
@@ -1575,16 +1671,6 @@ class stable_vector
       this->insert_not_iter(position, first, last);
    }
 
-   static void swap_impl(stable_vector& x,stable_vector& y)
-   {
-      using std::swap;
-      swap(x.get_al(),y.get_al());
-      swap(x.impl,y.impl);
-      swap(x.internal_data.pool_size, y.internal_data.pool_size);
-      x.readjust_end_node();
-      y.readjust_end_node();
-   }
-
    #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
    bool invariant()const
    {
@@ -1609,9 +1695,12 @@ class stable_vector
       return n >= num_pool;
    }
 
-   class invariant_checker:private boost::noncopyable
+   class invariant_checker
    {
+      invariant_checker(const invariant_checker &);
+      invariant_checker & operator=(const invariant_checker &);
       const stable_vector* p;
+
       public:
       invariant_checker(const stable_vector& v):p(&v){}
       ~invariant_checker(){BOOST_ASSERT(p->invariant());}
@@ -1619,11 +1708,32 @@ class stable_vector
    };
    #endif
 
-   struct ebo_holder
-      : node_allocator_type
+   class ebo_holder
+      : public node_allocator_type
    {
-      ebo_holder(const allocator_type &a)
-         : node_allocator_type(a), pool_size(0), end_node()
+      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(x)))
+         , pool_size(0)
+         , end_node()
+      {}
+*/
+      template
+      explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
+         : node_allocator_type(boost::forward(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();
       }
@@ -1637,8 +1747,15 @@ class stable_vector
       node_type_base_t end_node;
    } internal_data;
 
-   node_allocator_type &get_al()              { return internal_data;  }
-   const node_allocator_type &get_al() const  { return 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;  }
 
    impl_type                           impl;
    /// @endcond
diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp
index 8df94ff..feb62cf 100644
--- a/include/boost/container/string.hpp
+++ b/include/boost/container/string.hpp
@@ -30,8 +30,8 @@
 // representations about the suitability of this software for any
 // purpose.  It is provided "as is" without express or implied warranty.
 
-#ifndef BOOST_CONTAINERS_STRING_HPP
-#define BOOST_CONTAINERS_STRING_HPP
+#ifndef BOOST_CONTAINER_STRING_HPP
+#define BOOST_CONTAINER_STRING_HPP
 
 #include 
 #include 
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -75,7 +76,7 @@ namespace container {
 #endif
 
 /// @cond
-namespace containers_detail {
+namespace container_detail {
 // ------------------------------------------------------------
 // Class basic_string_base.  
 
@@ -89,16 +90,20 @@ namespace containers_detail {
 template 
 class basic_string_base
 {
-   basic_string_base();
    BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_string_base)
 
+   typedef allocator_traits allocator_traits_type;
  public:
    typedef A allocator_type;
    //! The stored allocator type
    typedef allocator_type                          stored_allocator_type;
-   typedef typename A::pointer     pointer;
-   typedef typename A::value_type  value_type;
-   typedef typename A::size_type   size_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;
+
+   basic_string_base()
+      : members_()
+   {  init(); }
 
    basic_string_base(const allocator_type& a)
       : members_(a)
@@ -112,16 +117,16 @@ class basic_string_base
    }
 
    basic_string_base(BOOST_RV_REF(basic_string_base) b)
-      :  members_(b.members_)
+      :  members_(boost::move(b.alloc()))
    {  
-      init();
-      this->swap(b); 
+      this->init();
+      this->swap_data(b); 
    }
 
    ~basic_string_base() 
    {  
-      this->deallocate_block(); 
       if(!this->is_short()){
+         this->deallocate_block(); 
          static_cast(static_cast(&this->members_.m_repr.r))->~long_t();
       }
    }
@@ -169,14 +174,14 @@ class basic_string_base
    //so, unlike long_t, it can be placed in a union
    
    typedef typename boost::aligned_storage< sizeof(long_t), 
-       containers_detail::alignment_of::value>::type   long_raw_t;
+       container_detail::alignment_of::value>::type   long_raw_t;
 
    protected:
    static const size_type  MinInternalBufferChars = 8;
    static const size_type  AlignmentOfValueType =
       alignment_of::value;
    static const size_type  ShortDataOffset =
-      containers_detail::ct_rounded_size::value;
+      container_detail::ct_rounded_size::value;
    static const size_type  ZeroCostInternalBufferChars =
       (sizeof(long_t) - ShortDataOffset)/sizeof(value_type);
    static const size_type  UnalignedFinalInternalBufferChars = 
@@ -204,8 +209,13 @@ class basic_string_base
    struct members_holder
       :  public A
    {
-      members_holder(const A &a)
-         :  A(a)
+      members_holder()
+         : A()
+      {}
+
+      template
+      explicit members_holder(BOOST_FWD_REF(AllocatorConvertible) a)
+         :  A(boost::forward(a))
       {}
 
       repr_t m_repr;
@@ -247,10 +257,10 @@ class basic_string_base
 
    protected:
 
-   typedef containers_detail::integral_constant      allocator_v1;
-   typedef containers_detail::integral_constant      allocator_v2;
-   typedef containers_detail::integral_constant::value> alloc_version;
+   typedef container_detail::integral_constant      allocator_v1;
+   typedef container_detail::integral_constant      allocator_v2;
+   typedef container_detail::integral_constant::value> alloc_version;
 
    std::pair
       allocation_command(allocation_type command,
@@ -295,7 +305,7 @@ class basic_string_base
    }
 
    size_type next_capacity(size_type additional_objects) const
-   {  return get_next_capacity(this->alloc().max_size(), this->priv_storage(), additional_objects);  }
+   {  return get_next_capacity(allocator_traits_type::max_size(this->alloc()), this->priv_storage(), additional_objects);  }
 
    void deallocate(pointer p, size_type n) 
    {  
@@ -304,16 +314,16 @@ class basic_string_base
    }
 
    void construct(pointer p, const value_type &value = value_type())
-   {  new((void*)containers_detail::get_pointer(p)) value_type(value);   }
+   {  new((void*)container_detail::to_raw_pointer(p)) value_type(value);   }
 
    void destroy(pointer p, size_type n)
    {
       for(; n--; ++p)
-         containers_detail::get_pointer(p)->~value_type();
+         container_detail::to_raw_pointer(p)->~value_type();
    }
 
    void destroy(pointer p)
-   {  containers_detail::get_pointer(p)->~value_type(); }
+   {  container_detail::to_raw_pointer(p)->~value_type(); }
 
    void allocate_initial_block(size_type n)
    {
@@ -335,7 +345,7 @@ class basic_string_base
    {  this->deallocate(this->priv_addr(), this->priv_storage());  }
       
    size_type max_size() const
-   {  return this->alloc().max_size() - 1; }
+   {  return allocator_traits_type::max_size(this->alloc()) - 1; }
 
    // Helper functions for exception handling.
    void throw_length_error() const
@@ -404,14 +414,14 @@ class basic_string_base
 
    void priv_long_size(size_type sz)
    {  
-      this->members_.m_repr.long_repr().length = static_cast(sz);
+      this->members_.m_repr.long_repr().length = static_cast(sz);
    }
 
-   void swap(basic_string_base& other)
+   void swap_data(basic_string_base& other)
    {
       if(this->is_short()){
          if(other.is_short()){
-            std::swap(this->members_.m_repr, other.members_.m_repr);
+            container_detail::do_swap(this->members_.m_repr, other.members_.m_repr);
          }
          else{
             repr_t copied(this->members_.m_repr);
@@ -426,18 +436,13 @@ class basic_string_base
             this->members_.m_repr = copied;
          }
          else{
-            std::swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
+            container_detail::do_swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
          }
       }
-
-      allocator_type & this_al = this->alloc(), &other_al = other.alloc();
-      if(this_al != other_al){
-         containers_detail::do_swap(this_al, other_al);
-      }
    }
 };
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 
 /// @endcond
 
@@ -475,12 +480,13 @@ template , class A = std::al
 template 
 #endif
 class basic_string
-   :  private containers_detail::basic_string_base 
+   :  private container_detail::basic_string_base 
 {
    /// @cond
    private:
+   typedef allocator_traits allocator_traits_type;
    BOOST_COPYABLE_AND_MOVABLE(basic_string)
-   typedef containers_detail::basic_string_base base_t;
+   typedef container_detail::basic_string_base base_t;
    static const typename base_t::size_type InternalBufferChars = base_t::InternalBufferChars;
 
    protected:
@@ -527,17 +533,17 @@ class basic_string
    //! The second template parameter Traits
    typedef Traits                                  traits_type;
    //! Pointer to CharT
-   typedef typename A::pointer                     pointer;
+   typedef typename allocator_traits_type::pointer pointer;
    //! Const pointer to CharT 
-   typedef typename A::const_pointer               const_pointer;
+   typedef typename allocator_traits_type::const_pointer               const_pointer;
    //! Reference to CharT 
-   typedef typename A::reference                   reference;
+   typedef typename allocator_traits_type::reference                   reference;
    //! Const reference to CharT 
-   typedef typename A::const_reference             const_reference;
+   typedef typename allocator_traits_type::const_reference             const_reference;
    //! An unsigned integral type
-   typedef typename A::size_type                   size_type;
+   typedef typename allocator_traits_type::size_type                   size_type;
    //! A signed integral type
-   typedef typename A::difference_type             difference_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
@@ -562,17 +568,28 @@ class basic_string
    struct reserve_t {};
 
    basic_string(reserve_t, size_type n,
-               const allocator_type& a = allocator_type())
-      : base_t(a, n + 1)
+                const allocator_type& a = allocator_type())
+      //Select allocator as in copy constructor as reserve_t-based constructors
+      //are two step copies optimized for capacity
+      : base_t( allocator_traits_type::select_on_container_copy_construction(a)
+              , n + 1)
    { this->priv_terminate_string(); }
 
    /// @endcond
 
+   //! Effects: Default constructs a basic_string.
+   //! 
+   //! Throws: If allocator_type's default constructor throws.
+   basic_string()
+      : base_t()
+   { this->priv_terminate_string(); }
+
+
    //! Effects: Constructs a basic_string taking the allocator as parameter.
    //! 
    //! Throws: If allocator_type's copy constructor throws.
-   explicit basic_string(const allocator_type& a = allocator_type())
-      : base_t(a, InternalBufferChars)
+   explicit basic_string(const allocator_type& a)
+      : base_t(a)
    { this->priv_terminate_string(); }
 
    //! Effects: Copy constructs a basic_string.
@@ -581,7 +598,7 @@ class basic_string
    //! 
    //! Throws: If allocator_type's default constructor or copy constructor throws.
    basic_string(const basic_string& s) 
-      : base_t(s.alloc()) 
+      :  base_t(allocator_traits_type::select_on_container_copy_construction(s.alloc()))
    { this->priv_range_initialize(s.begin(), s.end()); }
 
    //! Effects: Move constructor. Moves mx's resources to *this.
@@ -603,7 +620,7 @@ class basic_string
          this->throw_out_of_range();
       else
          this->priv_range_initialize
-            (s.begin() + pos, s.begin() + pos + containers_detail::min_value(n, s.size() - pos));
+            (s.begin() + pos, s.begin() + pos + container_detail::min_value(n, s.size() - pos));
    }
 
    //! Effects: Constructs a basic_string taking the allocator as parameter,
@@ -638,8 +655,8 @@ class basic_string
       : base_t(a)
    {
       //Dispatch depending on integer/iterator
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_initialize_dispatch(f, l, Result());
    }
 
@@ -656,10 +673,24 @@ class basic_string
    //! Postcondition: x == *this.
    //! 
    //! Complexity: Linear to the elements x contains.
-   basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) s)
+   basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
    {
-      if (&s != this) 
-         this->assign(s.begin(), s.end());
+      if (&x != this){
+         allocator_type &this_alloc     = this->alloc();
+         const allocator_type &x_alloc  = x.alloc();
+         container_detail::bool_ flag;
+         if(flag && this_alloc != x_alloc){
+            if(!this->is_short()){
+               this->deallocate_block();
+               this->is_short(true);
+               Traits::assign(*this->priv_addr(), this->priv_null());
+               this->priv_size(0);
+            }
+         }
+         container_detail::assign_alloc(this->alloc(), x.alloc(), flag);
+         this->assign(x.begin(), x.end());
+      }
       return *this;
    }
 
@@ -668,11 +699,25 @@ class basic_string
    //! Throws: If allocator_type's copy constructor throws.
    //! 
    //! Complexity: Constant.
-   basic_string& operator=(BOOST_RV_REF(basic_string) ms)
+   basic_string& operator=(BOOST_RV_REF(basic_string) x)
    {
-      basic_string &s = ms;
-      if (&s != this){
-         this->swap(s);
+      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_ 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());
+         }
       }
       return *this;
    }
@@ -709,7 +754,6 @@ class basic_string
    const_iterator cbegin() const
    { return this->priv_addr(); }
 
-
    //! Effects: Returns an iterator to the end of the vector.
    //! 
    //! Throws: Nothing.
@@ -796,6 +840,26 @@ class basic_string
    allocator_type get_allocator() const 
    { return this->alloc(); }
 
+   //! Effects: Returns a reference to the internal allocator.
+   //! 
+   //! Throws: Nothing
+   //! 
+   //! Complexity: Constant.
+   //! 
+   //! Note: Non-standard extension.
+   const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
+   {  return this->alloc(); }
+
+   //! Effects: Returns a reference to the internal allocator.
+   //! 
+   //! Throws: Nothing
+   //! 
+   //! Complexity: Constant.
+   //! 
+   //! Note: Non-standard extension.
+   stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
+   {  return this->alloc(); }
+
    //! Effects: Returns the number of the elements contained in the vector.
    //! 
    //! Throws: Nothing.
@@ -855,7 +919,7 @@ class basic_string
          this->throw_length_error();
 
       if (this->capacity() < res_arg){
-         size_type n = containers_detail::max_value(res_arg, this->size()) + 1;
+         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;
@@ -912,8 +976,8 @@ class basic_string
             size_type long_storage = this->priv_long_storage();
             size_type long_size    = this->priv_long_size();
             //Shrink from allocated buffer to the internal one, including trailing null
-            Traits::copy( containers_detail::get_pointer(this->priv_short_addr())
-                        , containers_detail::get_pointer(long_addr)
+            Traits::copy( container_detail::to_raw_pointer(this->priv_short_addr())
+                        , container_detail::to_raw_pointer(long_addr)
                         , long_size+1);
             this->is_short(true);
             this->alloc().deallocate(long_addr, long_storage);
@@ -1020,7 +1084,7 @@ class basic_string
       if (pos > s.size())
       this->throw_out_of_range();
       return this->append(s.begin() + pos,
-                          s.begin() + pos + containers_detail::min_value(n, s.size() - pos));
+                          s.begin() + pos + container_detail::min_value(n, s.size() - pos));
    }
 
    //! Requires: s points to an array of at least n elements of CharT.
@@ -1087,7 +1151,7 @@ class basic_string
    //!
    //! Returns: *this
    basic_string& assign(BOOST_RV_REF(basic_string) ms) 
-   {  return this->swap(ms), *this;  }
+   {  return this->swap_data(ms), *this;  }
 
    //! Requires: pos <= str.size()
    //!
@@ -1102,7 +1166,7 @@ class basic_string
       if (pos > s.size())
       this->throw_out_of_range();
       return this->assign(s.begin() + pos, 
-                          s.begin() + pos + containers_detail::min_value(n, s.size() - pos));
+                          s.begin() + pos + container_detail::min_value(n, s.size() - pos));
    }
 
    //! Requires: s points to an array of at least n elements of CharT.
@@ -1137,8 +1201,8 @@ class basic_string
    basic_string& assign(InputIter first, InputIter last) 
    {
       //Dispatch depending on integer/iterator
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       return this->priv_assign_dispatch(first, last, Result());
    }
 
@@ -1172,10 +1236,10 @@ class basic_string
    {
       if (pos1 > this->size() || pos2 > s.size())
          this->throw_out_of_range();
-      size_type len = containers_detail::min_value(n, s.size() - pos2);
+      size_type len = container_detail::min_value(n, s.size() - pos2);
       if (this->size() > this->max_size() - len)
          this->throw_length_error();
-      const CharT *beg_ptr = containers_detail::get_pointer(s.begin()) + pos2;
+      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);
       return *this;
@@ -1271,8 +1335,8 @@ class basic_string
    void insert(const_iterator p, InputIter first, InputIter last) 
    {
       //Dispatch depending on integer/iterator
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_insert_dispatch(p, first, last, Result());
    }
 
@@ -1291,7 +1355,7 @@ class basic_string
    {
       if (pos > size())
          this->throw_out_of_range();
-      erase(this->priv_addr() + pos, this->priv_addr() + pos + containers_detail::min_value(n, size() - pos));
+      erase(this->priv_addr() + pos, this->priv_addr() + pos + container_detail::min_value(n, size() - pos));
       return *this;
    }  
 
@@ -1304,9 +1368,9 @@ class basic_string
    iterator erase(const_iterator p) 
    {
       // The move includes the terminating null.
-      CharT *ptr = const_cast(containers_detail::get_pointer(p));
+      CharT *ptr = const_cast(container_detail::to_raw_pointer(p));
       Traits::move(ptr,
-                   containers_detail::get_pointer(p + 1), 
+                   container_detail::to_raw_pointer(p + 1), 
                    this->priv_size() - (p - this->priv_addr()));
       this->priv_size(this->priv_size()-1);
       return iterator(ptr);
@@ -1322,11 +1386,11 @@ class basic_string
    //!   the other elements being erased. If no such element exists, end() is returned.
    iterator erase(const_iterator first, const_iterator last)
    {
-      CharT * f = const_cast(containers_detail::get_pointer(first));
+      CharT * f = const_cast(container_detail::to_raw_pointer(first));
       if (first != last) { // The move includes the terminating null.
          size_type num_erased = last - first;
          Traits::move(f,
-                      containers_detail::get_pointer(last), 
+                      container_detail::to_raw_pointer(last), 
                       (this->priv_size() + 1)-(last - this->priv_addr()));
          size_type new_length = this->priv_size() - num_erased;
          this->priv_size(new_length);
@@ -1356,7 +1420,7 @@ class basic_string
    {
       if (pos1 > size())
          this->throw_out_of_range();
-      const size_type len = containers_detail::min_value(n1, size() - pos1);
+      const size_type len = container_detail::min_value(n1, 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, 
@@ -1377,8 +1441,8 @@ class basic_string
    {
       if (pos1 > size() || pos2 > str.size())
          this->throw_out_of_range();
-      const size_type len1 = containers_detail::min_value(n1, size() - pos1);
-      const size_type len2 = containers_detail::min_value(n2, str.size() - pos2);
+      const size_type len1 = container_detail::min_value(n1, 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,
@@ -1404,7 +1468,7 @@ class basic_string
    {
       if (pos1 > size())
          this->throw_out_of_range();
-      const size_type len = containers_detail::min_value(n1, size() - pos1);
+      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,
@@ -1429,7 +1493,7 @@ class basic_string
    {
       if (pos > size())
          this->throw_out_of_range();
-      const size_type len = containers_detail::min_value(n1, size() - pos);
+      const size_type len = container_detail::min_value(n1, size() - pos);
       const size_type n2 = Traits::length(s);
       if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
          this->throw_length_error();
@@ -1449,7 +1513,7 @@ class basic_string
    {
       if (pos1 > size())
          this->throw_out_of_range();
-      const size_type len = containers_detail::min_value(n1, size() - pos1);
+      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);
@@ -1498,11 +1562,11 @@ class basic_string
    {
       const size_type len = static_cast(i2 - i1);
       if (len >= n) {
-         Traits::assign(const_cast(containers_detail::get_pointer(i1)), n, c);
+         Traits::assign(const_cast(container_detail::to_raw_pointer(i1)), n, c);
          erase(i1 + n, i2);
       }
       else {
-         Traits::assign(const_cast(containers_detail::get_pointer(i1)), len, c);
+         Traits::assign(const_cast(container_detail::to_raw_pointer(i1)), len, c);
          insert(i2, n - len, c);
       }
       return *this;
@@ -1519,8 +1583,8 @@ class basic_string
    basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2) 
    {
       //Dispatch depending on integer/iterator
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       return this->priv_replace_dispatch(i1, i2, j1, j2,  Result());
    }
 
@@ -1539,8 +1603,8 @@ class basic_string
    {
       if (pos > size())
          this->throw_out_of_range();
-      const size_type len = containers_detail::min_value(n, size() - pos);
-      Traits::copy(s, containers_detail::get_pointer(this->priv_addr() + pos), len);
+      const size_type len = container_detail::min_value(n, size() - pos);
+      Traits::copy(s, container_detail::to_raw_pointer(this->priv_addr() + pos), len);
       return len;
    }
 
@@ -1549,7 +1613,11 @@ class basic_string
    //!
    //! Throws: Nothing
    void swap(basic_string& x)
-   {  base_t::swap(x);  }
+   {
+      this->base_t::swap_data(x);
+      container_detail::bool_ flag;
+      container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
+   }
 
    //! Requires: The program shall not alter any of the values stored in the character array.
    //!
@@ -1557,7 +1625,7 @@ class basic_string
    //!
    //! Complexity: constant time.
    const CharT* c_str() const 
-   {  return containers_detail::get_pointer(this->priv_addr()); }
+   {  return container_detail::to_raw_pointer(this->priv_addr()); }
 
    //! Requires: The program shall not alter any of the values stored in the character array.
    //!
@@ -1565,7 +1633,7 @@ class basic_string
    //!
    //! Complexity: constant time.
    const CharT* data()  const 
-   {  return containers_detail::get_pointer(this->priv_addr()); }
+   {  return container_detail::to_raw_pointer(this->priv_addr()); }
 
    //! Effects: Determines the lowest position xpos, if possible, such that both 
    //!   of the following conditions obtain: 19 pos <= xpos and xpos + str.size() <= size();
@@ -1589,8 +1657,8 @@ class basic_string
       else {
          pointer finish = this->priv_addr() + this->priv_size();
          const const_iterator result =
-            std::search(containers_detail::get_pointer(this->priv_addr() + pos), 
-                   containers_detail::get_pointer(finish),
+            std::search(container_detail::to_raw_pointer(this->priv_addr() + pos), 
+                   container_detail::to_raw_pointer(finish),
                    s, s + n, Eq_traits());
          return result != finish ? result - begin() : npos;
       }
@@ -1643,9 +1711,9 @@ class basic_string
       if (n > len)
          return npos;
       else if (n == 0)
-         return containers_detail::min_value(len, pos);
+         return container_detail::min_value(len, pos);
       else {
-         const const_iterator last = begin() + containers_detail::min_value(len - n, pos) + n;
+         const const_iterator last = begin() + container_detail::min_value(len - n, pos) + n;
          const const_iterator result = find_end(begin(), last,
                                                 s, s + n,
                                                 Eq_traits());
@@ -1672,7 +1740,7 @@ class basic_string
       if (len < 1)
          return npos;
       else {
-         const const_iterator last = begin() + containers_detail::min_value(len - 1, pos) + 1;
+         const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
          const_reverse_iterator rresult =
             std::find_if(const_reverse_iterator(last), rend(),
                   std::bind2nd(Eq_traits(), c));
@@ -1746,7 +1814,7 @@ class basic_string
       if (len < 1)
          return npos;
       else {
-         const const_iterator last = this->priv_addr() + containers_detail::min_value(len - 1, pos) + 1;
+         const const_iterator last = this->priv_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,
@@ -1843,7 +1911,7 @@ class basic_string
       if (len < 1)
          return npos;
       else {
-         const const_iterator last = begin() + containers_detail::min_value(len - 1, pos) + 1;
+         const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
          const const_reverse_iterator rresult =
             std::find_if(const_reverse_iterator(last), rend(),
                     Not_within_traits(s, s + n));
@@ -1869,7 +1937,7 @@ class basic_string
       if (len < 1)
          return npos;
       else {
-         const const_iterator last = begin() + containers_detail::min_value(len - 1, pos) + 1;
+         const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
          const_reverse_iterator rresult =
             std::find_if(const_reverse_iterator(last), rend(),
                   std::not1(std::bind2nd(Eq_traits(), c)));
@@ -1890,7 +1958,7 @@ class basic_string
       if (pos > size())
          this->throw_out_of_range();
       return basic_string(this->priv_addr() + pos, 
-                          this->priv_addr() + pos + containers_detail::min_value(n, size() - pos), this->alloc());
+                          this->priv_addr() + pos + container_detail::min_value(n, size() - pos), this->alloc());
    }
 
    //! Effects: Determines the effective length rlen of the string to copy as
@@ -1918,7 +1986,7 @@ class basic_string
       if (pos1 > size())
          this->throw_out_of_range();
       return s_compare(this->priv_addr() + pos1, 
-                        this->priv_addr() + pos1 + containers_detail::min_value(n1, size() - pos1),
+                        this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1),
                         str.priv_addr(), str.priv_addr() + str.priv_size());
    }
 
@@ -1935,9 +2003,9 @@ class basic_string
       if (pos1 > size() || pos2 > str.size())
          this->throw_out_of_range();
       return s_compare(this->priv_addr() + pos1, 
-                        this->priv_addr() + pos1 + containers_detail::min_value(n1, size() - pos1),
+                        this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1),
                         str.priv_addr() + pos2, 
-                        str.priv_addr() + pos2 + containers_detail::min_value(n2, size() - pos2));
+                        str.priv_addr() + pos2 + container_detail::min_value(n2, size() - pos2));
    }
 
    //! Throws: Nothing
@@ -1958,7 +2026,7 @@ class basic_string
       if (pos1 > size())
          this->throw_out_of_range();
       return s_compare(this->priv_addr() + pos1, 
-                        this->priv_addr() + pos1 + containers_detail::min_value(n1, size() - pos1),
+                        this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1),
                         s, s + n2);
    }
 
@@ -1977,13 +2045,16 @@ class basic_string
    {
       const difference_type n1 = l1 - f1;
       const difference_type n2 = l2 - f2;
-      const int cmp = Traits::compare(containers_detail::get_pointer(f1), 
-                                      containers_detail::get_pointer(f2), 
-                                      containers_detail::min_value(n1, n2));
+      const int cmp = Traits::compare(container_detail::to_raw_pointer(f1), 
+                                      container_detail::to_raw_pointer(f2), 
+                                      container_detail::min_value(n1, n2));
       return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
    }
 
-   void priv_shrink_to_fit_dynamic_buffer(allocator_v1)
+   template
+   void priv_shrink_to_fit_dynamic_buffer
+      ( AllocVersion
+      , typename container_detail::enable_if >::type* = 0)
    {
       //Allocate a new buffer.
       size_type real_cap = 0;
@@ -1995,8 +2066,8 @@ class basic_string
          std::pair ret = this->allocation_command
                (allocate_new, long_size+1, long_size+1, real_cap, long_addr);
          //Copy and update
-         Traits::copy( containers_detail::get_pointer(ret.first)
-                     , containers_detail::get_pointer(this->priv_long_addr())
+         Traits::copy( container_detail::to_raw_pointer(ret.first)
+                     , container_detail::to_raw_pointer(this->priv_long_addr())
                      , long_size+1);
          this->priv_long_addr(ret.first);
          this->priv_storage(real_cap);
@@ -2008,7 +2079,10 @@ class basic_string
       }
    }
 
-   void priv_shrink_to_fit_dynamic_buffer(allocator_v2)
+   template
+   void priv_shrink_to_fit_dynamic_buffer
+      ( AllocVersion 
+      , typename container_detail::enable_if >::type* = 0)
    {
       size_type received_size;
       if(this->alloc().allocation_command
@@ -2044,7 +2118,7 @@ class basic_string
                               std::forward_iterator_tag)
    {
       difference_type n = std::distance(f, l);
-      this->allocate_initial_block(containers_detail::max_value(n+1, InternalBufferChars));
+      this->allocate_initial_block(container_detail::max_value(n+1, InternalBufferChars));
       priv_uninitialized_copy(f, l, this->priv_addr());
       this->priv_size(n);
       this->priv_terminate_string();
@@ -2058,16 +2132,16 @@ class basic_string
    }
 
    template 
-   void priv_initialize_dispatch(Integer n, Integer x, containers_detail::true_)
+   void priv_initialize_dispatch(Integer n, Integer x, container_detail::true_)
    {
-      this->allocate_initial_block(containers_detail::max_value(n+1, InternalBufferChars));
+      this->allocate_initial_block(container_detail::max_value(n+1, InternalBufferChars));
       priv_uninitialized_fill_n(this->priv_addr(), n, x);
       this->priv_size(n);
       this->priv_terminate_string();
    }
 
    template 
-   void priv_initialize_dispatch(InputIter f, InputIter l, containers_detail::false_)
+   void priv_initialize_dispatch(InputIter f, InputIter l, container_detail::false_)
    {  this->priv_range_initialize(f, l);  }
  
    template inline
@@ -2117,15 +2191,15 @@ class basic_string
    }
 
    template 
-   basic_string& priv_assign_dispatch(Integer n, Integer x, containers_detail::true_) 
+   basic_string& priv_assign_dispatch(Integer n, Integer x, container_detail::true_) 
    {  return this->assign((size_type) n, (CharT) x);   }
 
    template 
    basic_string& priv_assign_dispatch(InputIter f, InputIter l,
-                                      containers_detail::false_)
+                                      container_detail::false_)
    {
       size_type cur = 0;
-      CharT *ptr = containers_detail::get_pointer(this->priv_addr());
+      CharT *ptr = container_detail::to_raw_pointer(this->priv_addr());
       while (f != l && cur != this->priv_size()) {
          Traits::assign(*ptr, *f);
          ++f;
@@ -2189,10 +2263,10 @@ class basic_string
                                        pointer_past_last, pointer_past_last);
 
                this->priv_size(this->priv_size()+n);
-               Traits::move(const_cast(containers_detail::get_pointer(position + n)),
-                           containers_detail::get_pointer(position),
+               Traits::move(const_cast(container_detail::to_raw_pointer(position + n)),
+                           container_detail::to_raw_pointer(position),
                            (elems_after - n) + 1);
-               this->priv_copy(first, last, const_cast(containers_detail::get_pointer(position)));
+               this->priv_copy(first, last, const_cast(container_detail::to_raw_pointer(position)));
             }
             else {
                ForwardIter mid = first;
@@ -2204,7 +2278,7 @@ class basic_string
                   (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(containers_detail::get_pointer(position)));
+               this->priv_copy(first, mid, const_cast(container_detail::to_raw_pointer(position)));
             }
          }
          else{
@@ -2231,9 +2305,9 @@ class basic_string
             else{
                //value_type is POD, so backwards expansion is much easier 
                //than with vector
-               value_type *oldbuf = containers_detail::get_pointer(old_start);
-               value_type *newbuf = containers_detail::get_pointer(new_start);
-               const value_type *pos    = containers_detail::get_pointer(position);
+               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
@@ -2253,12 +2327,12 @@ class basic_string
 
    template 
    void priv_insert_dispatch(const_iterator p, Integer n, Integer x,
-                           containers_detail::true_) 
+                           container_detail::true_) 
    {  insert(p, (size_type) n, (CharT) x);   }
 
    template 
    void priv_insert_dispatch(const_iterator p, InputIter first, InputIter last,
-                           containers_detail::false_) 
+                           container_detail::false_) 
    {
       typedef typename std::iterator_traits::iterator_category Category;
       priv_insert(p, first, last, Category());
@@ -2277,13 +2351,13 @@ class basic_string
    template 
    basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
                                        Integer n, Integer x,
-                                       containers_detail::true_) 
+                                       container_detail::true_) 
    {  return this->replace(first, last, (size_type) n, (CharT) x);   }
 
    template 
    basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
                                        InputIter f, InputIter l,
-                                       containers_detail::false_) 
+                                       container_detail::false_) 
    {
       typedef typename std::iterator_traits::iterator_category Category;
       return this->priv_replace(first, last, f, l, Category());
@@ -2312,13 +2386,13 @@ class basic_string
       difference_type n = std::distance(f, l);
       const difference_type len = last - first;
       if (len >= n) {
-         this->priv_copy(f, l, const_cast(containers_detail::get_pointer(first)));
+         this->priv_copy(f, l, const_cast(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(containers_detail::get_pointer(first)));
+         this->priv_copy(f, m, const_cast(container_detail::to_raw_pointer(first)));
          this->insert(last, m, l);
       }
       return *this;
@@ -2364,10 +2438,20 @@ operator+(const basic_string& x,
    typedef basic_string str_t;
    typedef typename str_t::reserve_t reserve_t;
    reserve_t reserve;
-   str_t result(reserve, x.size() + y.size(), x.alloc());
+   str_t result(reserve, x.size() + y.size(), x.get_stored_allocator());
    result.append(x);
    result.append(y);
-   return result;
+   return boost::move(result);
+}
+
+template  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)
+{
+   mx += my;
+   return boost::move(mx);
 }
 
 template  inline
@@ -2386,7 +2470,8 @@ BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
          BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
 {
    typedef typename basic_string::size_type size_type;
-   return my.replace(size_type(0), size_type(0), x);
+   my.replace(size_type(0), size_type(0), x);
+   return boost::move(my);
 }
 
 template 
@@ -2400,7 +2485,7 @@ operator+(const CharT* s, const basic_string& y)
    str_t result(reserve, n + y.size());
    result.append(s, s + n);
    result.append(y);
-   return result;
+   return boost::move(result);
 }
 
 template  inline
@@ -2409,7 +2494,7 @@ operator+(const CharT* s,
          BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
 {
    typedef typename basic_string::size_type size_type;
-   return boost::move(my.get().replace(size_type(0), size_type(0), s));
+   return boost::move(my.replace(size_type(0), size_type(0), s));
 }
 
 template 
@@ -2422,7 +2507,7 @@ operator+(CharT c, const basic_string& y)
    str_t result(reserve, 1 + y.size());
    result.push_back(c);
    result.append(y);
-   return result;
+   return boost::move(result);
 }
 
 template  inline
@@ -2431,7 +2516,7 @@ operator+(CharT c,
          BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
 {
    typedef typename basic_string::size_type size_type;
-   return my.replace(size_type(0), size_type(0), &c, &c + 1);
+   return boost::move(my.replace(size_type(0), size_type(0), &c, &c + 1));
 }
 
 template 
@@ -2442,10 +2527,10 @@ operator+(const basic_string& x, const CharT* s)
    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.alloc());
+   str_t result(reserve, x.size() + n, x.get_stored_allocator());
    result.append(x);
    result.append(s, s + n);
-   return result;
+   return boost::move(result);
 }
 
 template 
@@ -2461,13 +2546,13 @@ template 
 inline basic_string
 operator+(const basic_string& x, const CharT c) 
 {
-  typedef basic_string str_t;
-  typedef typename str_t::reserve_t reserve_t;
+   typedef basic_string str_t;
+   typedef typename str_t::reserve_t reserve_t;
    reserve_t reserve;
-   str_t result(reserve, x.size() + 1, x.alloc());
+   str_t result(reserve, x.size() + 1, x.get_stored_allocator());
    result.append(x);
    result.push_back(c);
-   return result;
+   return boost::move(result);
 }
 
 template 
@@ -2616,7 +2701,7 @@ inline void swap(basic_string& x, basic_string&
 
 /// @cond
 // I/O.  
-namespace containers_detail {
+namespace container_detail {
 
 template 
 inline bool
@@ -2633,7 +2718,7 @@ string_fill(std::basic_ostream& os,
    return ok;
 }
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 /// @endcond
 
 template 
@@ -2655,13 +2740,13 @@ operator<<(std::basic_ostream& os, const basic_stringsputn(s.data(), std::streamsize(n)) == std::streamsize(n);
 
       if (left)
-         ok = ok && containers_detail::string_fill(os, buf, pad_len);
+         ok = ok && container_detail::string_fill(os, buf, pad_len);
    }
 
    if (!ok)
@@ -2783,4 +2868,4 @@ struct has_trivial_destructor_after_move
 
 #include 
 
-#endif // BOOST_CONTAINERS_STRING_HPP
+#endif // BOOST_CONTAINER_STRING_HPP
diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp
index be1a222..7a2aa4f 100644
--- a/include/boost/container/vector.hpp
+++ b/include/boost/container/vector.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINERS_CONTAINERS_VECTOR_HPP
-#define BOOST_CONTAINERS_CONTAINERS_VECTOR_HPP
+#ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP
+#define BOOST_CONTAINER_CONTAINER_VECTOR_HPP
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 #  pragma once
@@ -31,17 +31,20 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
-#include 
+#include 
+#include 
 #include 
+#include 
 #include 
 
 namespace boost {
@@ -49,25 +52,19 @@ namespace container {
 
 /// @cond
 
-namespace containers_detail {
+namespace container_detail {
 
 //! Const vector_iterator used to iterate through a vector. 
 template 
 class vector_const_iterator
-   : public std::iterator::value_type
-                          ,typename std::iterator_traits::difference_type
-                          ,typename boost::pointer_to_other
-                              ::value_type
-                              >::type
-                          ,const typename std::iterator_traits::value_type &>
 {
    public:
-   typedef typename std::iterator_traits::value_type  value_type;
-   typedef typename std::iterator_traits::difference_type   difference_type;
-   typedef typename boost::pointer_to_other::type      pointer;
-   typedef const value_type&                                               reference;
+	typedef std::random_access_iterator_tag                                          iterator_category;
+   typedef typename boost::intrusive::pointer_traits::element_type         value_type;
+   typedef typename boost::intrusive::pointer_traits::difference_type      difference_type;
+   typedef typename boost::intrusive::pointer_traits::template
+                                 rebind_pointer::type             pointer;
+   typedef  const value_type&                                                       reference;
 
    /// @cond
    protected:
@@ -88,7 +85,7 @@ class vector_const_iterator
    {  return *m_ptr;  }
 
    const value_type * operator->()  const  
-   {  return  containers_detail::get_pointer(m_ptr);  }
+   {  return  container_detail::to_raw_pointer(m_ptr);  }
 
    reference operator[](difference_type off) const
    {  return m_ptr[off];   }
@@ -156,10 +153,11 @@ class vector_iterator
    {}
 
    public:
-   typedef typename std::iterator_traits::value_type        value_type;
-   typedef typename vector_const_iterator::difference_type  difference_type;
-   typedef Pointer                                                   pointer;
-   typedef value_type&                                               reference;
+	typedef std::random_access_iterator_tag                                       iterator_category;
+   typedef typename boost::intrusive::pointer_traits::element_type      value_type;
+   typedef typename boost::intrusive::pointer_traits::difference_type   difference_type;
+   typedef Pointer                                                               pointer;
+   typedef value_type&                                                           reference;
 
    //Constructors
    vector_iterator()
@@ -170,7 +168,7 @@ class vector_iterator
    {  return *this->m_ptr;  }
 
    value_type* operator->() const  
-   {  return  containers_detail::get_pointer(this->m_ptr);  }
+   {  return  container_detail::to_raw_pointer(this->m_ptr);  }
 
    reference operator[](difference_type off) const 
    {  return this->m_ptr[off];   }
@@ -216,30 +214,35 @@ struct vector_value_traits
    static const bool trivial_dctr = boost::has_trivial_destructor::value;
    static const bool trivial_dctr_after_move = trivial_dctr;
       //::boost::has_trivial_destructor_after_move::value || trivial_dctr;
+   //static const bool trivial_copy = has_trivial_copy::value;
+   //static const bool nothrow_copy = has_nothrow_copy::value;
+   //static const bool trivial_assign = has_trivial_assign::value;
+   //static const bool nothrow_assign = has_nothrow_assign::value;
+
    static const bool trivial_copy = has_trivial_copy::value;
    static const bool nothrow_copy = has_nothrow_copy::value;
    static const bool trivial_assign = has_trivial_assign::value;
-   static const bool nothrow_assign = has_nothrow_assign::value;
+   static const bool nothrow_assign = false;
 
    //This is the anti-exception array destructor
    //to deallocate values already constructed
-   typedef typename containers_detail::if_c
+   typedef typename container_detail::if_c
       
-      ,containers_detail::scoped_destructor_n
+      ,container_detail::null_scoped_destructor_n
+      ,container_detail::scoped_destructor_n
       >::type   OldArrayDestructor;
    //This is the anti-exception array destructor
    //to destroy objects created with copy construction
-   typedef typename containers_detail::if_c
+   typedef typename container_detail::if_c
       
-      ,containers_detail::scoped_destructor_n
+      ,container_detail::null_scoped_destructor_n
+      ,container_detail::scoped_destructor_n
       >::type   ArrayDestructor;
    //This is the anti-exception array deallocator
-   typedef typename containers_detail::if_c
+   typedef typename container_detail::if_c
       
-      ,containers_detail::scoped_array_deallocator
+      ,container_detail::null_scoped_array_deallocator
+      ,container_detail::scoped_array_deallocator
       >::type   ArrayDeallocator;
 };
 
@@ -247,14 +250,22 @@ struct vector_value_traits
 template 
 struct vector_alloc_holder 
 {
-   typedef typename A::pointer      pointer;
-   typedef typename A::size_type    size_type;
-   typedef typename A::value_type   value_type;
-   typedef vector_value_traits value_traits;
+   typedef boost::container::allocator_traits         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_traits;
 
    //Constructor, does not throw
-   vector_alloc_holder(const A &a)
-      : members_(a)
+   vector_alloc_holder()
+      BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor::value)
+      : members_()
+   {}
+
+   //Constructor, does not throw
+   template
+   explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_CONTAINER_NOEXCEPT
+      : members_(boost::forward(a))
    {}
 
    //Destructor
@@ -264,10 +275,10 @@ struct vector_alloc_holder
       this->prot_deallocate();
    }
 
-   typedef containers_detail::integral_constant      allocator_v1;
-   typedef containers_detail::integral_constant      allocator_v2;
-   typedef containers_detail::integral_constant::value> alloc_version;
+   typedef container_detail::integral_constant      allocator_v1;
+   typedef container_detail::integral_constant      allocator_v2;
+   typedef container_detail::integral_constant::value> alloc_version;
    std::pair
       allocation_command(allocation_type command,
                          size_type limit_size, 
@@ -307,7 +318,10 @@ struct vector_alloc_holder
    }
 
    size_type next_capacity(size_type additional_objects) const
-   {  return get_next_capacity(this->alloc().max_size(), this->members_.m_capacity, additional_objects);  }
+   {
+      return get_next_capacity( allocator_traits_type::max_size(this->alloc())
+                              , this->members_.m_capacity, additional_objects);
+   }
 
    struct members_holder
       : public A
@@ -316,8 +330,13 @@ struct vector_alloc_holder
       members_holder(const members_holder&);
 
       public:
-      members_holder(const A &alloc)
-         :  A(alloc), m_start(0), m_size(0), m_capacity(0)
+      template
+      explicit members_holder(BOOST_FWD_REF(Alloc) alloc)
+         :  A(boost::forward(alloc)), m_start(0), m_size(0), m_capacity(0)
+      {}
+
+      members_holder()
+         :  A(), m_start(0), m_size(0), m_capacity(0)
       {}
 
       pointer     m_start;
@@ -325,6 +344,13 @@ struct vector_alloc_holder
       size_type   m_capacity;
    } members_;
 
+   void swap_members(vector_alloc_holder &x)
+   {
+      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);
+   }
+
    A &alloc()
    {  return members_;  }
 
@@ -344,23 +370,26 @@ struct vector_alloc_holder
    void destroy(value_type* p)
    {
       if(!value_traits::trivial_dctr)
-         containers_detail::get_pointer(p)->~value_type();
+         allocator_traits_type::destroy(this->alloc(), p);
    }
 
    void destroy_n(value_type* p, size_type n)
    {
-      if(!value_traits::trivial_dctr)
-         for(; n--; ++p)   p->~value_type();
+      if(!value_traits::trivial_dctr){
+         for(; n--; ++p){
+            allocator_traits_type::destroy(this->alloc(), p);
+         }
+      }
    }
 
    void prot_destroy_all()
    {
-      this->destroy_n(containers_detail::get_pointer(this->members_.m_start), this->members_.m_size);
+      this->destroy_n(container_detail::to_raw_pointer(this->members_.m_start), this->members_.m_size);
       this->members_.m_size = 0;
    }
 };
 
-}  //namespace containers_detail {
+}  //namespace container_detail {
 /// @endcond
 
 //! \class vector
@@ -375,33 +404,34 @@ template  >
 #else
 template 
 #endif
-class vector : private containers_detail::vector_alloc_holder
+class vector : private container_detail::vector_alloc_holder
 {
    /// @cond
    typedef vector                   self_t;
-   typedef containers_detail::vector_alloc_holder base_t;
+   typedef container_detail::vector_alloc_holder base_t;
+   typedef allocator_traits            allocator_traits_type;
    /// @endcond
    public:
    //! The type of object, T, stored in the vector
-   typedef T                                       value_type;
+   typedef T                                                value_type;
    //! Pointer to T
-   typedef typename A::pointer                     pointer;
+   typedef typename allocator_traits_type::pointer          pointer;
    //! Const pointer to T
-   typedef typename A::const_pointer               const_pointer;
+   typedef typename allocator_traits_type::const_pointer    const_pointer;
    //! Reference to T
-   typedef typename A::reference                   reference;
+   typedef typename allocator_traits_type::reference        reference;
    //! Const reference to T
-   typedef typename A::const_reference             const_reference;
+   typedef typename allocator_traits_type::const_reference  const_reference;
    //! An unsigned integral type
-   typedef typename A::size_type                   size_type;
+   typedef typename allocator_traits_type::size_type        size_type;
    //! A signed integral type
-   typedef typename A::difference_type             difference_type;
+   typedef typename allocator_traits_type::difference_type  difference_type;
    //! The allocator type
    typedef A                                       allocator_type;
    //! The random access iterator
-   typedef containers_detail::vector_iterator        iterator;
+   typedef container_detail::vector_iterator        iterator;
    //! The random access const_iterator
-   typedef containers_detail::vector_const_iterator  const_iterator;
+   typedef container_detail::vector_const_iterator  const_iterator;
 
    //! Iterator used to iterate backwards through a vector. 
    typedef std::reverse_iterator   
@@ -415,8 +445,8 @@ class vector : private containers_detail::vector_alloc_holder
    /// @cond
    private:
    BOOST_COPYABLE_AND_MOVABLE(vector)
-   typedef containers_detail::advanced_insert_aux_int    advanced_insert_aux_int_t;
-   typedef containers_detail::vector_value_traits value_traits;
+   typedef container_detail::advanced_insert_aux_int    advanced_insert_aux_int_t;
+   typedef container_detail::vector_value_traits value_traits;
 
    typedef typename base_t::allocator_v1           allocator_v1;
    typedef typename base_t::allocator_v2           allocator_v2;
@@ -431,33 +461,43 @@ class vector : private containers_detail::vector_alloc_holder
 
    //! Effects: Constructs a vector taking the allocator as parameter.
    //! 
-   //! Throws: If allocator_type's copy constructor throws.
+   //! Throws: If allocator_type's default constructor throws.
    //! 
    //! Complexity: Constant.
-   explicit vector(const A& a = A())
+   vector()
+      BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor::value)
+      : base_t()
+   {}
+
+   //! Effects: Constructs a vector taking the allocator as parameter.
+   //! 
+   //! Throws: Nothing
+   //! 
+   //! Complexity: Constant.
+   explicit vector(const A& a) BOOST_CONTAINER_NOEXCEPT
       : base_t(a)
    {}
 
    //! Effects: Constructs a vector that will use a copy of allocator a
    //!   and inserts n default contructed values.
    //!
-   //! Throws: If allocator_type's default constructor or copy constructor
-   //!   throws or T's default or copy constructor throws.
+   //! Throws: If allocator_type's default constructor or allocation
+   //!   throws or T's default constructor throws.
    //! 
    //! Complexity: Linear to n.
-   explicit vector(size_type n) 
-      :  base_t(allocator_type())
+   explicit vector(size_type n)
+      :  base_t()
    {
       //Allocate
       size_type real_cap;
       std::pair ret =
          this->allocation_command(allocate_new, n, n, real_cap, this->members_.m_start);
-      T *new_mem = containers_detail::get_pointer(ret.first);
+      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
-      containers_detail::default_construct_aux_proxy proxy(n);
-      proxy.uninitialized_copy_all_to(new_mem);
+      container_detail::default_construct_aux_proxy 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;
@@ -468,8 +508,8 @@ class vector : private containers_detail::vector_alloc_holder
    //! Effects: Constructs a vector that will use a copy of allocator a
    //!   and inserts n copies of value.
    //!
-   //! Throws: If allocator_type's default constructor or copy constructor
-   //!   throws or T's default or copy constructor throws.
+   //! Throws: If allocator_type's default constructor or allocation
+   //!   throws or T's copy constructor throws.
    //! 
    //! Complexity: Linear to n.
    vector(size_type n, const T& value, const allocator_type& a = allocator_type()) 
@@ -480,24 +520,30 @@ class vector : private containers_detail::vector_alloc_holder
    //!
    //! Postcondition: x == *this.
    //! 
+   //! Throws: If allocator_type's default constructor or allocation
+   //!   throws or T's copy constructor throws.
+   //! 
    //! Complexity: Linear to the elements x contains.
-   vector(const vector& x) 
-      :  base_t(static_cast(x).alloc())
-   {  *this = x;  }
+   vector(const vector &x) 
+      :  base_t(allocator_traits_type::select_on_container_copy_construction(x.alloc()))
+   {
+      this->assign( container_detail::to_raw_pointer(x.members_.m_start)
+                  , container_detail::to_raw_pointer(x.members_.m_start + x.members_.m_size));
+   }
 
    //! Effects: Move constructor. Moves mx's resources to *this.
    //!
-   //! Throws: If allocator_type's copy constructor throws.
+   //! Throws: Nothing
    //! 
    //! Complexity: Constant.
-   vector(BOOST_RV_REF(vector) mx) 
-      :  base_t(static_cast(mx).alloc())
-   {  this->swap(mx);   }
+   vector(BOOST_RV_REF(vector) mx) BOOST_CONTAINER_NOEXCEPT
+      :  base_t(boost::move(mx.alloc()))
+   {  this->swap_members(mx);   }
 
    //! Effects: Constructs a vector that will use a copy of allocator a
    //!   and inserts a copy of the range [first, last) in the vector.
    //!
-   //! Throws: If allocator_type's default constructor or copy constructor
+   //! Throws: If allocator_type's default constructor or allocation
    //!   throws or T's constructor taking an dereferenced InIt throws.
    //!
    //! Complexity: Linear to the range [first, last).
@@ -512,7 +558,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //!
    //! Complexity: Linear to the number of elements.
-   ~vector() 
+   ~vector() BOOST_CONTAINER_NOEXCEPT
    {} //vector_alloc_holder clears the data
 
    //! Effects: Returns an iterator to the first element contained in the vector.
@@ -520,7 +566,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   iterator begin()      
+   iterator begin() BOOST_CONTAINER_NOEXCEPT
    { return iterator(this->members_.m_start); }
 
    //! Effects: Returns a const_iterator to the first element contained in the vector.
@@ -528,7 +574,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_iterator begin() const
+   const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
    { return const_iterator(this->members_.m_start); }
 
    //! Effects: Returns an iterator to the end of the vector.
@@ -536,7 +582,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   iterator end()        
+   iterator end() BOOST_CONTAINER_NOEXCEPT
    { return iterator(this->members_.m_start + this->members_.m_size); }
 
    //! Effects: Returns a const_iterator to the end of the vector.
@@ -544,7 +590,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_iterator end()   const
+   const_iterator end() const BOOST_CONTAINER_NOEXCEPT
    { return this->cend(); }
 
    //! Effects: Returns a reverse_iterator pointing to the beginning 
@@ -553,7 +599,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   reverse_iterator rbegin()     
+   reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
    { return reverse_iterator(this->end());      }
 
    //! Effects: Returns a const_reverse_iterator pointing to the beginning 
@@ -562,7 +608,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reverse_iterator rbegin()const
+   const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
    { return this->crbegin(); }
 
    //! Effects: Returns a reverse_iterator pointing to the end
@@ -571,7 +617,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   reverse_iterator rend()       
+   reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
    { return reverse_iterator(this->begin());       }
 
    //! Effects: Returns a const_reverse_iterator pointing to the end
@@ -580,7 +626,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reverse_iterator rend()  const
+   const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
    { return this->crend(); }
 
    //! Effects: Returns a const_iterator to the first element contained in the vector.
@@ -588,7 +634,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_iterator cbegin() const
+   const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
    { return const_iterator(this->members_.m_start); }
 
    //! Effects: Returns a const_iterator to the end of the vector.
@@ -596,7 +642,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_iterator cend()   const
+   const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
    { return const_iterator(this->members_.m_start + this->members_.m_size); }
 
    //! Effects: Returns a const_reverse_iterator pointing to the beginning 
@@ -605,7 +651,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reverse_iterator crbegin()const
+   const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
    { return const_reverse_iterator(this->end());}
 
    //! Effects: Returns a const_reverse_iterator pointing to the end
@@ -614,7 +660,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reverse_iterator crend()  const
+   const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
    { return const_reverse_iterator(this->begin()); }
 
    //! Requires: !empty()
@@ -625,7 +671,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   reference         front()       
+   reference         front() BOOST_CONTAINER_NOEXCEPT
    { return *this->members_.m_start; }
 
    //! Requires: !empty()
@@ -636,7 +682,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reference   front() const 
+   const_reference   front() const BOOST_CONTAINER_NOEXCEPT
    { return *this->members_.m_start; }
 
    //! Requires: !empty()
@@ -647,7 +693,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   reference         back()        
+   reference         back() BOOST_CONTAINER_NOEXCEPT
    { return this->members_.m_start[this->members_.m_size - 1]; }
 
    //! Requires: !empty()
@@ -658,7 +704,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reference   back()  const 
+   const_reference   back()  const BOOST_CONTAINER_NOEXCEPT
    { return this->members_.m_start[this->members_.m_size - 1]; }
 
    //! Returns: A pointer such that [data(),data() + size()) is a valid range.
@@ -667,7 +713,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   pointer data()        
+   pointer data() BOOST_CONTAINER_NOEXCEPT
    { return this->members_.m_start; }
 
    //! Returns: A pointer such that [data(),data() + size()) is a valid range.
@@ -676,7 +722,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_pointer data()  const 
+   const_pointer data()  const BOOST_CONTAINER_NOEXCEPT
    { return this->members_.m_start; }
 
    //! Effects: Returns the number of the elements contained in the vector.
@@ -684,7 +730,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   size_type size() const 
+   size_type size() const BOOST_CONTAINER_NOEXCEPT
    { return this->members_.m_size; }
 
    //! Effects: Returns the largest possible size of the vector.
@@ -692,8 +738,8 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   size_type max_size() const 
-   { return this->alloc().max_size(); }
+   size_type max_size() const BOOST_CONTAINER_NOEXCEPT
+   { return allocator_traits_type::max_size(this->alloc()); }
 
    //! Effects: Number of elements for which memory has been allocated.
    //!   capacity() is always greater than or equal to size().
@@ -701,7 +747,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   size_type capacity() const 
+   size_type capacity() const BOOST_CONTAINER_NOEXCEPT
    { return this->members_.m_capacity; }
 
    //! Effects: Returns true if the vector contains no elements.
@@ -709,7 +755,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   bool empty() const 
+   bool empty() const BOOST_CONTAINER_NOEXCEPT
    { return !this->members_.m_size; }
 
    //! Requires: size() < n.
@@ -731,7 +777,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //! 
    //! Complexity: Constant.
-   const_reference operator[](size_type n) const   
+   const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
    { return this->members_.m_start[n]; }
 
    //! Requires: size() < n.
@@ -742,7 +788,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: std::range_error if n >= size()
    //! 
    //! Complexity: Constant.
-   reference at(size_type n)
+   reference at(size_type n) 
    { this->priv_check_range(n); return this->members_.m_start[n]; }
 
    //! Requires: size() < n.
@@ -761,13 +807,27 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: If allocator's copy constructor throws.
    //! 
    //! Complexity: Constant.
-   allocator_type get_allocator() const 
+   allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
    { return this->alloc();  }
 
-   const stored_allocator_type &get_stored_allocator() const 
+   //! Effects: Returns a reference to the internal allocator.
+   //! 
+   //! Throws: Nothing
+   //! 
+   //! Complexity: Constant.
+   //! 
+   //! Note: Non-standard extension.
+   const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
    {  return this->alloc(); }
 
-   stored_allocator_type &get_stored_allocator()
+   //! Effects: Returns a reference to the internal allocator.
+   //! 
+   //! Throws: Nothing
+   //! 
+   //! Complexity: Constant.
+   //! 
+   //! Note: Non-standard extension.
+   stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
    {  return this->alloc(); }
 
    //! Effects: If n is less than or equal to capacity(), this call has no
@@ -791,7 +851,7 @@ class vector : private containers_detail::vector_alloc_holder
          //Check for forward expansion
          same_buffer_start = ret.second && this->members_.m_start == ret.first;
          if(same_buffer_start){
-            #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
+            #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
             ++this->num_expand_fwd;
             #endif
             this->members_.m_capacity  = real_cap;
@@ -800,30 +860,30 @@ class vector : private containers_detail::vector_alloc_holder
          //If there is no forward expansion, move objects
          else{
             //We will reuse insert code, so create a dummy input iterator
-            T *dummy_it(containers_detail::get_pointer(this->members_.m_start));
-            containers_detail::advanced_insert_aux_proxy, T*>
-               proxy(::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it));
+            T *dummy_it(container_detail::to_raw_pointer(this->members_.m_start));
+            container_detail::advanced_insert_aux_proxy, 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_CONTAINERS_VECTOR_ALLOC_STATS
+               #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
                ++this->num_expand_bwd;
                #endif
                this->priv_range_insert_expand_backwards
-                  ( containers_detail::get_pointer(ret.first)
+                  ( container_detail::to_raw_pointer(ret.first)
                   , real_cap
-                  , containers_detail::get_pointer(this->members_.m_start)
+                  , container_detail::to_raw_pointer(this->members_.m_start)
                   , 0
                   , proxy);
             }
             //New buffer
             else{
-               #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
+               #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
                ++this->num_alloc;
                #endif
                this->priv_range_insert_new_allocation
-                  ( containers_detail::get_pointer(ret.first)
+                  ( container_detail::to_raw_pointer(ret.first)
                   , real_cap
-                  , containers_detail::get_pointer(this->members_.m_start)
+                  , container_detail::to_raw_pointer(this->members_.m_start)
                   , 0
                   , proxy);
             }
@@ -836,13 +896,23 @@ class vector : private containers_detail::vector_alloc_holder
    //! Postcondition: this->size() == x.size(). *this contains a copy 
    //! of each of x's elements. 
    //!
-   //! Throws: If memory allocation throws or T's copy constructor throws.
+   //! Throws: If memory allocation throws or T's copy/move constructor/assignment throws.
    //!
    //! Complexity: Linear to the number of elements in x.
    vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
    {
       if (&x != this){
-         this->assign(x.members_.m_start, x.members_.m_start + x.members_.m_size);
+         allocator_type &this_alloc     = this->alloc();
+         const allocator_type &x_alloc  = x.alloc();
+         container_detail::bool_ 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;
    }
@@ -852,21 +922,39 @@ class vector : private containers_detail::vector_alloc_holder
    //! Postcondition: x.empty(). *this contains a the elements x had
    //!   before the function.
    //!
-   //! Throws: If allocator_type's copy constructor throws.
+   //! Throws: Nothing
    //!
    //! Complexity: 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::value);)
+      BOOST_CONTAINER_NOEXCEPT
    {
       if (&x != this){
-         this->swap(x);
-         x.clear();
+         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_ 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;
    }
 
    //! Effects: Assigns the n copies of val to *this.
    //!
-   //! Throws: If memory allocation throws or T's copy constructor throws.
+   //! Throws: If memory allocation throws or
+   //!   T's copy/move constructor/assignment throws.
    //!
    //! Complexity: Linear to n.
    void assign(size_type n, const value_type& val)
@@ -874,16 +962,16 @@ class vector : private containers_detail::vector_alloc_holder
 
    //! Effects: Assigns the the range [first, last) to *this.
    //!
-   //! Throws: If memory allocation throws or
-   //!   T's constructor from dereferencing InpIt throws.
+   //! Throws: If memory allocation throws or T's copy/move constructor/assignment or
+   //!   T's constructor/assignment from dereferencing InpIt throws.
    //!
    //! Complexity: Linear to n.
    template 
    void assign(InIt first, InIt last) 
    {
       //Dispatch depending on integer/iterator
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_assign_dispatch(first, last, Result());
    }
 
@@ -891,7 +979,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Effects: Inserts a copy of x at the end of the vector.
    //!
    //! Throws: If memory allocation throws or
-   //!   T's copy constructor throws.
+   //!   T's copy/move constructor throws.
    //!
    //! Complexity: Amortized constant time.
    void push_back(const T &x);
@@ -899,7 +987,8 @@ class vector : private containers_detail::vector_alloc_holder
    //! Effects: Constructs a new element in the end of the vector
    //!   and moves the resources of mx to this new element.
    //!
-   //! Throws: If memory allocation throws.
+   //! Throws: If memory allocation throws or
+   //!   T's move constructor throws.
    //!
    //! Complexity: Amortized constant time.
    void push_back(T &&x);
@@ -907,69 +996,26 @@ class vector : private containers_detail::vector_alloc_holder
    BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
    #endif
 
-/*
-   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(x)); }
-
-   template
-   typename containers_detail::enable_if_c
-                     ::value &&
-                     containers_detail::is_same::value
-                     >::type
-   push_back(const U &u)
-   { return priv_push_back(u); }
-
-   #endif
-
-   //! Effects: Constructs a new element in the end of the vector
-   //!   and moves the resources of mx to this new element.
-   //!
-   //! Throws: If memory allocation throws.
-   //!
-   //! Complexity: Amortized constant time.
-   void push_back(BOOST_RV_REF(T) x)
-   {
-      if (this->members_.m_size < this->members_.m_capacity){
-         //There is more memory, just construct a new object at the end
-         new((void*)containers_detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(::boost::move(x));
-         ++this->members_.m_size;
-      }
-      else{
-         this->insert(this->cend(), ::boost::move(x));
-      }
-   }
-*/
-   //! Effects: Constructs a new element in the end of the vector
-   //!   and moves the resources of mx to this new element.
-   //!
-   //! Throws: If memory allocation throws.
-   //!
-   //! Complexity: Amortized constant time.
-
-
-   #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
-
+   #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... in the end of the vector.
    //!
-   //! Throws: If memory allocation throws or the in-place constructor throws.
+   //! Throws: If memory allocation throws or the in-place constructor throws or
+   //!   T's move constructor throws.
    //!
    //! Complexity: Amortized constant time.
    template
    void emplace_back(Args &&...args)
    {
-      T* back_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size;
+      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){
          //There is more memory, just construct a new object at the end
-         new((void*)(back_pos))value_type(::boost::forward(args)...);
+         allocator_traits_type::construct(this->alloc(), back_pos, ::boost::forward(args)...);
          ++this->members_.m_size;
       }
       else{
-         typedef containers_detail::advanced_insert_aux_emplace type;
-         type &&proxy = type(::boost::forward(args)...);
+         typedef container_detail::advanced_insert_aux_emplace type;
+         type &&proxy = type(this->alloc(), ::boost::forward(args)...);
          priv_range_insert(back_pos, 1, proxy);
       }
    }
@@ -979,7 +1025,8 @@ class vector : private containers_detail::vector_alloc_holder
    //! Effects: Inserts an object of type T constructed with
    //!   std::forward(args)... before position
    //!
-   //! Throws: If memory allocation throws or the in-place constructor throws.
+   //! Throws: If memory allocation throws or the in-place constructor throws or
+   //!   T's move constructor/assignment throws.
    //!
    //! Complexity: If position is end(), amortized constant time
    //!   Linear time otherwise.
@@ -988,69 +1035,49 @@ class vector : private containers_detail::vector_alloc_holder
    {
       //Just call more general insert(pos, size, value) and return iterator
       size_type pos_n = position - cbegin();
-      typedef containers_detail::advanced_insert_aux_emplace type;
-      type &&proxy = type(::boost::forward(args)...);
+      typedef container_detail::advanced_insert_aux_emplace type;
+      type &&proxy = type(this->alloc(), ::boost::forward(args)...);
       priv_range_insert(position.get_ptr(), 1, proxy);
       return iterator(this->members_.m_start + pos_n);
    }
 
    #else
 
-   void emplace_back()
-   {
-      T* back_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size;
-      if (this->members_.m_size < this->members_.m_capacity){
-         //There is more memory, just construct a new object at the end
-         new((void*)(back_pos))value_type();
-         ++this->members_.m_size;
-      }
-      else{
-         containers_detail::advanced_insert_aux_emplace proxy;
-         priv_range_insert(back_pos, 1, proxy);
-      }
-   }
-
-   iterator emplace(const_iterator position)
-   {
-      size_type pos_n = position - cbegin();
-      containers_detail::advanced_insert_aux_emplace proxy;
-      priv_range_insert(containers_detail::get_pointer(position.get_ptr()), 1, proxy);
-      return iterator(this->members_.m_start + pos_n);
-   }
-
    #define BOOST_PP_LOCAL_MACRO(n)                                                              \
-   template                                                   \
-   void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_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, _))                       \
    {                                                                                            \
-      T* back_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size;        \
+      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){                                   \
-         new((void*)(back_pos))value_type                                                       \
-            (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                           \
+         allocator_traits_type::construct (this->alloc()                                        \
+            , back_pos BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) );       \
          ++this->members_.m_size;                                                               \
       }                                                                                         \
       else{                                                                                     \
-         containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)     \
-                                                    \
-               proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                   \
+         container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)     \
+             proxy                                   \
+            (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));    \
          priv_range_insert(back_pos, 1, proxy);                                                 \
       }                                                                                         \
    }                                                                                            \
                                                                                                 \
-   template                                                   \
-   iterator emplace(const_iterator pos, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))    \
+   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();                                                         \
-      containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)        \
-                                                    \
-            proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                      \
-      priv_range_insert(containers_detail::get_pointer(pos.get_ptr()), 1, proxy);               \
+         container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)     \
+             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_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
+   #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
    #include BOOST_PP_LOCAL_ITERATE()
 
-   #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
+   #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
   
    //! Effects: Swaps the contents of *this and x.
    //!   If this->allocator_type() != x.allocator_type()
@@ -1061,15 +1088,11 @@ class vector : private containers_detail::vector_alloc_holder
    //! Complexity: Constant.
    void swap(vector& x)
    {
-      allocator_type &this_al = this->alloc(), &other_al = x.alloc();
       //Just swap internals
-      containers_detail::do_swap(this->members_.m_start, x.members_.m_start);
-      containers_detail::do_swap(this->members_.m_size, x.members_.m_size);
-      containers_detail::do_swap(this->members_.m_capacity, x.members_.m_capacity);
-
-      if (this_al != other_al){
-         containers_detail::do_swap(this_al, other_al);
-      }
+      this->swap_members(x);
+      //And now the allocator
+      container_detail::bool_ flag;
+      container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
    }
 
    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1077,7 +1100,7 @@ class vector : private containers_detail::vector_alloc_holder
    //!
    //! Effects: Insert a copy of x before position.
    //!
-   //! Throws: If memory allocation throws or x's copy constructor throws.
+   //! Throws: If memory allocation throws or T's copy/move constructor/assignment throws.
    //!
    //! Complexity: If position is end(), amortized constant time
    //!   Linear time otherwise.
@@ -1101,15 +1124,15 @@ class vector : private containers_detail::vector_alloc_holder
    //! Effects: Insert a copy of the [first, last) range before pos.
    //!
    //! Throws: If memory allocation throws, T's constructor from a
-   //!   dereferenced InpIt throws or T's copy constructor throws.
+   //!   dereferenced InpIt throws or T's copy/move constructor/assignment throws.
    //!
    //! Complexity: Linear to std::distance [first, last).
    template 
    void insert(const_iterator pos, InIt first, InIt last)
    {
       //Dispatch depending on integer/iterator
-      const bool aux_boolean = containers_detail::is_convertible::value;
-      typedef containers_detail::bool_ Result;
+      const bool aux_boolean = container_detail::is_convertible::value;
+      typedef container_detail::bool_ Result;
       this->priv_insert_dispatch(pos, first, last, Result());
    }
 
@@ -1132,7 +1155,7 @@ class vector : private containers_detail::vector_alloc_holder
    {
       //Destroy last element
       --this->members_.m_size;
-      this->destroy(containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size);
+      this->destroy(container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size);
    }
 
    //! Effects: Erases the element at position pos.
@@ -1143,12 +1166,12 @@ class vector : private containers_detail::vector_alloc_holder
    //!   last element. Constant if pos is the last element.
    iterator erase(const_iterator position) 
    {
-      T *pos = containers_detail::get_pointer(position.get_ptr());
-      T *beg = containers_detail::get_pointer(this->members_.m_start);
+      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(containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size);
+      base_t::destroy(container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size);
       return iterator(position.get_ptr());
    }
 
@@ -1161,11 +1184,11 @@ class vector : private containers_detail::vector_alloc_holder
    iterator erase(const_iterator first, const_iterator last) 
    {
       if (first != last){   // worth doing, copy down over hole
-         T* end_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size;
-         T* ptr = containers_detail::get_pointer(boost::move
-            (containers_detail::get_pointer(last.get_ptr())
+         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
-            ,containers_detail::get_pointer(first.get_ptr())
+            ,container_detail::to_raw_pointer(first.get_ptr())
             ));
          size_type destroyed = (end_pos - ptr);
          this->destroy_n(ptr, destroyed);
@@ -1208,7 +1231,7 @@ class vector : private containers_detail::vector_alloc_holder
       else{
          size_type n = new_size - this->size();
          this->reserve(new_size);
-         containers_detail::default_construct_aux_proxy proxy(n);
+         container_detail::default_construct_aux_proxy proxy(this->alloc(), n);
          priv_range_insert(this->cend().get_ptr(), n, proxy);
       }
    }
@@ -1218,7 +1241,7 @@ class vector : private containers_detail::vector_alloc_holder
    //! Throws: Nothing.
    //!
    //! Complexity: Linear to the number of elements in the vector.
-   void clear() 
+   void clear() BOOST_CONTAINER_NOEXCEPT
    {  this->prot_destroy_all();  }
 
    //! Effects: Tries to deallocate the excess of memory created
@@ -1256,7 +1279,10 @@ class vector : private containers_detail::vector_alloc_holder
    {
       if (this->members_.m_size < this->members_.m_capacity){
          //There is more memory, just construct a new object at the end
-         new((void*)containers_detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(::boost::forward(x));
+         allocator_traits_type::construct
+            ( this->alloc()
+            , container_detail::to_raw_pointer(this->members_.m_start + this->members_.m_size)
+            , ::boost::forward(x) );
          ++this->members_.m_size;
       }
       else{
@@ -1264,7 +1290,10 @@ class vector : private containers_detail::vector_alloc_holder
       }
    }
 
-   void priv_shrink_to_fit(allocator_v1)
+   template
+   void priv_shrink_to_fit( AllocVersion
+                          , typename container_detail::enable_if_c<
+                              container_detail::is_same::value >::type * = 0)
    {
       if(this->members_.m_capacity){
          if(!size()){
@@ -1278,16 +1307,16 @@ class vector : private containers_detail::vector_alloc_holder
                   (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(containers_detail::get_pointer(this->members_.m_start));
-               containers_detail::advanced_insert_aux_proxy, T*>
-                  proxy(::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it));
-               #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
+               T *dummy_it(container_detail::to_raw_pointer(this->members_.m_start));
+               container_detail::advanced_insert_aux_proxy, 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
-                  ( containers_detail::get_pointer(ret.first)
+                  ( container_detail::to_raw_pointer(ret.first)
                   , real_cap
-                  , containers_detail::get_pointer(this->members_.m_start)
+                  , container_detail::to_raw_pointer(this->members_.m_start)
                   , 0
                   , proxy);
             }
@@ -1298,7 +1327,10 @@ class vector : private containers_detail::vector_alloc_holder
       }
    }
 
-   void priv_shrink_to_fit(allocator_v2)
+   template
+   void priv_shrink_to_fit(AllocVersion
+                          , typename container_detail::enable_if_c<
+                              container_detail::is_same::value >::type * = 0)
    {
       if(this->members_.m_capacity){
          if(!size()){
@@ -1311,7 +1343,7 @@ class vector : private containers_detail::vector_alloc_holder
                , this->capacity(), this->size()
                , received_size,   this->members_.m_start).first){
                this->members_.m_capacity = received_size;
-               #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
+               #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
                ++this->num_shrink;
                #endif
             }
@@ -1324,7 +1356,7 @@ class vector : private containers_detail::vector_alloc_holder
    {
       if(first != last){        
          const size_type n = std::distance(first, last);
-         containers_detail::advanced_insert_aux_proxy proxy(first, last);
+         container_detail::advanced_insert_aux_proxy proxy(this->alloc(), first, last);
          priv_range_insert(pos.get_ptr(), n, proxy);
       }
    }
@@ -1366,33 +1398,33 @@ class vector : private containers_detail::vector_alloc_holder
       
       //If we had room or we have expanded forward
       if (same_buffer_start){
-         #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
+         #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
          ++this->num_expand_fwd;
          #endif
          this->priv_range_insert_expand_forward
-            (containers_detail::get_pointer(pos), n, interf);
+            (container_detail::to_raw_pointer(pos), n, interf);
       }
       //Backwards (and possibly forward) expansion
       else if(ret.second){
-         #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
+         #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
          ++this->num_expand_bwd;
          #endif
          this->priv_range_insert_expand_backwards
-            ( containers_detail::get_pointer(ret.first)
+            ( container_detail::to_raw_pointer(ret.first)
             , real_cap
-            , containers_detail::get_pointer(pos)
+            , container_detail::to_raw_pointer(pos)
             , n
             , interf);
       }
       //New buffer
       else{
-         #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
+         #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
          ++this->num_alloc;
          #endif
          this->priv_range_insert_new_allocation
-            ( containers_detail::get_pointer(ret.first)
+            ( container_detail::to_raw_pointer(ret.first)
             , real_cap
-            , containers_detail::get_pointer(pos)
+            , container_detail::to_raw_pointer(pos)
             , n
             , interf);
       }
@@ -1403,18 +1435,19 @@ class vector : private containers_detail::vector_alloc_holder
       //n can't be 0, because there is nothing to do in that case
       if(!n) return;
       //There is enough memory
-      T* old_finish = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size;
+      T* old_finish = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size;
       const size_type elems_after = old_finish - pos;
 
-      if (elems_after > n){
+      if (elems_after >= n){
          //New elements can be just copied.
          //Move to uninitialized memory last objects
-         ::boost::uninitialized_move(old_finish - n, old_finish, old_finish);
+         ::boost::container::uninitialized_move_alloc
+            (this->alloc(), old_finish - n, old_finish, old_finish);
          this->members_.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_all_to(pos);
+         interf.copy_remaining_to(pos);
       }
       else {
          //The new elements don't fit in the [pos, end()) range. Copy
@@ -1422,11 +1455,11 @@ class vector : private containers_detail::vector_alloc_holder
          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::uninitialized_move
-            ( pos, old_finish, containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size);
+         ::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_all_to(pos);
+         interf.copy_remaining_to(pos);
       }
    }
 
@@ -1438,25 +1471,25 @@ class vector : private containers_detail::vector_alloc_holder
       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, 0u);
+      typename value_traits::ArrayDestructor constructed_values_destroyer(new_start, this->alloc(), 0u);
 
       //Initialize with [begin(), pos) old buffer 
       //the start of the new buffer
-      T *old_buffer = containers_detail::get_pointer(this->members_.m_start);
+      T *old_buffer = container_detail::to_raw_pointer(this->members_.m_start);
       if(old_buffer){
-         new_finish = ::boost::uninitialized_move
-            (containers_detail::get_pointer(this->members_.m_start), pos, old_finish = new_finish);
+         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);
       }
       //Initialize new objects, starting from previous point
-      interf.uninitialized_copy_all_to(old_finish = new_finish);
+      interf.uninitialized_copy_remaining_to(old_finish = new_finish);
       new_finish += n;
       constructed_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::uninitialized_move
-            (pos, old_buffer + this->members_.m_size, new_finish);
+         new_finish = ::boost::container::uninitialized_move_alloc
+            (this->alloc(), pos, old_buffer + this->members_.m_size, new_finish);
          //Destroy and deallocate old elements
          //If there is allocated memory, destroy and deallocate
          if(!value_traits::trivial_dctr_after_move)
@@ -1477,7 +1510,7 @@ class vector : private containers_detail::vector_alloc_holder
    {
       //n can be zero to just expand capacity
       //Backup old data
-      T* old_start  = containers_detail::get_pointer(this->members_.m_start);
+      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;
 
@@ -1492,13 +1525,13 @@ class vector : private containers_detail::vector_alloc_holder
 
       //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, old_size);
+      typename value_traits::OldArrayDestructor old_values_destroyer(old_start, this->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)){
          //Copy first old values before pos, after that the new objects
-         ::boost::uninitialized_move(old_start, pos, new_start);
+         ::boost::container::uninitialized_move_alloc(this->alloc(), old_start, pos, new_start);
          this->members_.m_size = elemsbefore;
-         interf.uninitialized_copy_all_to(new_start + elemsbefore);
+         interf.uninitialized_copy_remaining_to(new_start + elemsbefore);
          this->members_.m_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
@@ -1514,8 +1547,8 @@ class vector : private containers_detail::vector_alloc_holder
             //|___________|__________|_________|________________________|
             //
             //Now initialize the rest of memory with the last old values
-            ::boost::uninitialized_move
-               (pos, old_finish, new_start + elemsbefore + n);
+            ::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;
             //Old values destroyed automatically with "old_values_destroyer"
@@ -1541,7 +1574,8 @@ class vector : private containers_detail::vector_alloc_holder
             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::uninitialized_move(pos, pos + raw_gap, new_start + elemsbefore + n);
+            ::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
@@ -1606,7 +1640,8 @@ class vector : private containers_detail::vector_alloc_holder
             //
             //Copy the first part of old_begin to raw_mem
             T *start_n = old_start + difference_type(s_before); 
-            ::boost::uninitialized_move(old_start, start_n, new_start);
+            ::boost::container::uninitialized_move_alloc
+               (this->alloc(), old_start, start_n, new_start);
             //The buffer is all constructed until old_end,
             //release destroyer and update size
             old_values_destroyer.release();
@@ -1619,7 +1654,7 @@ class vector : private containers_detail::vector_alloc_holder
             }
             else{
                //Now copy the all the new elements
-               interf.copy_all_to(next);
+               interf.copy_remaining_to(next);
                T* move_start = next + n;
                //Now displace old_end elements
                T* move_end   = ::boost::move(pos, old_finish, move_start);
@@ -1658,7 +1693,8 @@ class vector : private containers_detail::vector_alloc_holder
             //|___________|_____|_________|__________________________|
             //
             //First copy whole old_begin and part of new to raw_mem
-            ::boost::uninitialized_move(old_start, pos, new_start);
+            ::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;
@@ -1674,7 +1710,7 @@ class vector : private containers_detail::vector_alloc_holder
             }
             else{
                //Copy all new elements
-               interf.copy_all_to(old_start);
+               interf.copy_remaining_to(old_start);
                T* move_start = old_start + (n-mid_n);
                //Displace old_end
                T* move_end = ::boost::move(pos, old_finish, move_start);
@@ -1728,13 +1764,14 @@ class vector : private containers_detail::vector_alloc_holder
                //
                //First copy the part of old_end raw_mem
                T* finish_n = old_finish - difference_type(n_after);
-               ::boost::uninitialized_move(finish_n, old_finish, old_finish);
+               ::boost::container::uninitialized_move_alloc
+                  (this->alloc(), finish_n, old_finish, old_finish);
                this->members_.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_all_to(pos);
+               interf.copy_remaining_to(pos);
             }
             else {
                //The raw_mem from end will divide new_end part
@@ -1754,10 +1791,11 @@ class vector : private containers_detail::vector_alloc_holder
                //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::uninitialized_move(pos, old_finish, old_finish + 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_all_to(pos);
+               interf.copy_remaining_to(pos);
             }
          }
       }
@@ -1812,7 +1850,7 @@ class vector : private containers_detail::vector_alloc_holder
       }
       
       if(same_buffer_start){
-         T *start = containers_detail::get_pointer(this->members_.m_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
@@ -1829,19 +1867,17 @@ class vector : private containers_detail::vector_alloc_holder
             // iG T *end = std::copy(first, mid, start);
             T *end = std::copy(first, mid, start);
             //Initialize the remaining new elements in the uninitialized memory
-            // iG std::uninitialized_copy(mid, last, end);
-            ::boost::uninitialized_copy_or_move(mid, last, end);
+            ::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);
-         // iG std::uninitialized_copy(first, last, containers_detail::get_pointer(ret.first));
-         ::boost::uninitialized_copy_or_move(first, last, containers_detail::get_pointer(ret.first));
+         ::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(containers_detail::get_pointer(this->members_.m_start), this->members_.m_size); 
+            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;
@@ -1851,9 +1887,9 @@ class vector : private containers_detail::vector_alloc_holder
       else{
          //Backwards expansion
          //If anything goes wrong, this object will destroy old objects
-         T *old_start         = containers_detail::get_pointer(this->members_.m_start);
+         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, old_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;
@@ -1861,13 +1897,13 @@ class vector : private containers_detail::vector_alloc_holder
          this->members_.m_capacity = real_cap;
          
          //Backup old buffer data
-         size_type old_offset    = old_start - containers_detail::get_pointer(ret.first);
-         size_type first_count   = containers_detail::min_value(n, old_offset);
+         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);
-         // iG std::uninitialized_copy(first, mid, containers_detail::get_pointer(ret.first));
-         ::boost::uninitialized_copy_or_move(first, mid, containers_detail::get_pointer(ret.first));
+         ::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" 
@@ -1880,7 +1916,7 @@ class vector : private containers_detail::vector_alloc_holder
             this->members_.m_start  = ret.first;
             this->members_.m_size   = first_count + old_size;
             //Now overwrite the old values
-            size_type second_count = containers_detail::min_value(old_size, n - first_count);
+            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);
@@ -1904,11 +1940,11 @@ class vector : private containers_detail::vector_alloc_holder
    }
 
    template 
-   void priv_assign_dispatch(Integer n, Integer val, containers_detail::true_)
+   void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
    { this->assign((size_type) n, (value_type)val); }
 
    template 
-   void priv_assign_dispatch(InIt first, InIt last, containers_detail::false_)
+   void priv_assign_dispatch(InIt first, InIt last, container_detail::false_)
    { 
       //Dispatch depending on integer/iterator
       typedef typename std::iterator_traits::iterator_category ItCat;
@@ -1916,12 +1952,12 @@ class vector : private containers_detail::vector_alloc_holder
    }
 
    template 
-   void priv_insert_dispatch(const_iterator pos, Integer n, Integer val, containers_detail::true_) 
+   void priv_insert_dispatch(const_iterator pos, Integer n, Integer val, container_detail::true_) 
    {  this->insert(pos, (size_type)n, (T)val);  }
 
    template 
    void priv_insert_dispatch(const_iterator pos, InIt first, 
-                             InIt last,      containers_detail::false_)
+                             InIt last,      container_detail::false_)
    {
       //Dispatch depending on integer/iterator
       typedef typename std::iterator_traits::iterator_category ItCat;
@@ -1935,7 +1971,7 @@ class vector : private containers_detail::vector_alloc_holder
          throw std::out_of_range("vector::at");
    }
 
-   #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
+   #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
    public:
    unsigned int num_expand_fwd;
    unsigned int num_expand_bwd;
@@ -1998,5 +2034,5 @@ struct has_trivial_destructor_after_move >
 
 #include 
 
-#endif //   #ifndef  BOOST_CONTAINERS_CONTAINERS_VECTOR_HPP
+#endif //   #ifndef  BOOST_CONTAINER_CONTAINER_VECTOR_HPP
 

From e7bae623012da072d568abe40e3b989db3e042b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= 
Date: Thu, 22 Dec 2011 20:15:57 +0000
Subject: [PATCH 08/14] Introducing allocator_traits and pointer_traits changes
 into several libraries.

[SVN r76107]
---
 proj/vc7ide/allocator_traits_test.vcproj      | 139 +++++++
 proj/vc7ide/container.sln                     |  52 ++-
 proj/vc7ide/container.vcproj                  | 282 +++++++-------
 .../{list_ex.vcproj => list_test.vcproj}      |   0
 proj/vc7ide/pair_test.vcproj                  | 133 +++++++
 test/allocator_traits_test.cpp                | 355 ++++++++++++++++++
 test/check_equal_containers.hpp               |   6 +-
 test/deque_test.cpp                           |  44 ++-
 test/dummy_test_allocator.hpp                 | 232 +++++++++++-
 test/emplace_test.hpp                         |  92 ++---
 test/expand_bwd_test_allocator.hpp            |  12 +-
 test/flat_tree_test.cpp                       | 148 +++++++-
 test/heap_allocator_v1.hpp                    |   2 +-
 test/list_test.cpp                            |  17 +
 test/list_test.hpp                            |   6 +-
 test/map_test.hpp                             |  25 +-
 test/movable_int.hpp                          |  39 ++
 test/pair_test.cpp                            |  54 +++
 test/propagate_allocator_test.hpp             | 181 +++++++++
 test/set_test.hpp                             |   1 +
 test/slist_test.cpp                           |  15 +
 test/stable_vector_test.cpp                   |  27 +-
 test/string_test.cpp                          | 221 +++++++++--
 test/tree_test.cpp                            | 157 +++++++-
 test/vector_test.cpp                          |  19 +-
 test/vector_test.hpp                          |   7 +-
 26 files changed, 1953 insertions(+), 313 deletions(-)
 create mode 100644 proj/vc7ide/allocator_traits_test.vcproj
 rename proj/vc7ide/{list_ex.vcproj => list_test.vcproj} (100%)
 create mode 100644 proj/vc7ide/pair_test.vcproj
 create mode 100644 test/allocator_traits_test.cpp
 create mode 100644 test/pair_test.cpp
 create mode 100644 test/propagate_allocator_test.hpp

diff --git a/proj/vc7ide/allocator_traits_test.vcproj b/proj/vc7ide/allocator_traits_test.vcproj
new file mode 100644
index 0000000..ad50eba
--- /dev/null
+++ b/proj/vc7ide/allocator_traits_test.vcproj
@@ -0,0 +1,139 @@
+
+
+	
+		
+	
+	
+		
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+		
+		
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+		
+	
+	
+	
+	
+		
+			
+			
+		
+		
+		
+	
+	
+	
+
diff --git a/proj/vc7ide/container.sln b/proj/vc7ide/container.sln
index ea29003..38cb19d 100644
--- a/proj/vc7ide/container.sln
+++ b/proj/vc7ide/container.sln
@@ -1,4 +1,12 @@
 Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_containerlib", "container.vcproj", "{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "allocator_traits_test", "allocator_traits_test.vcproj", "{5CE11C83-096A-84FE-4FA2-D3A6BA792002}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deque_test", "deque_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792655}"
 	ProjectSection(ProjectDependencies) = postProject
 	EndProjectSection
@@ -7,7 +15,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flat_tree_test", "flat_tree
 	ProjectSection(ProjectDependencies) = postProject
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list_test", "list_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792632}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist_test", "slist_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792608}"
 	ProjectSection(ProjectDependencies) = postProject
 	EndProjectSection
 EndProject
@@ -23,15 +31,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tree_test", "tree_test.vcpr
 	ProjectSection(ProjectDependencies) = postProject
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist_test", "slist_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792608}"
-	ProjectSection(ProjectDependencies) = postProject
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vector_test", "vector_test.vcproj", "{5CE11C83-096A-84FE-4FA2-D3A6BA792002}"
 	ProjectSection(ProjectDependencies) = postProject
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_containerlib", "container.vcproj", "{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pair_test", "pair_test.vcproj", "{58CA17C5-A74F-9602-48FE-B06310DA7FA6}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list_test", "list_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792632}"
 	ProjectSection(ProjectDependencies) = postProject
 	EndProjectSection
 EndProject
@@ -43,6 +51,14 @@ Global
 	GlobalSection(ProjectDependencies) = postSolution
 	EndGlobalSection
 	GlobalSection(ProjectConfiguration) = postSolution
+		{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Debug.ActiveCfg = Debug|Win32
+		{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Debug.Build.0 = Debug|Win32
+		{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Release.ActiveCfg = Release|Win32
+		{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Release.Build.0 = Release|Win32
+		{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.ActiveCfg = Debug|Win32
+		{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.Build.0 = Debug|Win32
+		{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.ActiveCfg = Release|Win32
+		{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.Build.0 = Release|Win32
 		{58CCE183-6092-48FE-A4F7-BA0D3A792655}.Debug.ActiveCfg = Debug|Win32
 		{58CCE183-6092-48FE-A4F7-BA0D3A792655}.Debug.Build.0 = Debug|Win32
 		{58CCE183-6092-48FE-A4F7-BA0D3A792655}.Release.ActiveCfg = Release|Win32
@@ -51,10 +67,10 @@ Global
 		{58CCE183-6092-48FE-A4F7-BA0D3A792637}.Debug.Build.0 = Debug|Win32
 		{58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.ActiveCfg = Release|Win32
 		{58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.Build.0 = Release|Win32
-		{58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.ActiveCfg = Debug|Win32
-		{58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.Build.0 = Debug|Win32
-		{58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.ActiveCfg = Release|Win32
-		{58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.Build.0 = Release|Win32
+		{58CCE183-6092-48FE-A4F7-BA0D3A792608}.Debug.ActiveCfg = Debug|Win32
+		{58CCE183-6092-48FE-A4F7-BA0D3A792608}.Debug.Build.0 = Debug|Win32
+		{58CCE183-6092-48FE-A4F7-BA0D3A792608}.Release.ActiveCfg = Release|Win32
+		{58CCE183-6092-48FE-A4F7-BA0D3A792608}.Release.Build.0 = Release|Win32
 		{5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Debug.ActiveCfg = Debug|Win32
 		{5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Debug.Build.0 = Debug|Win32
 		{5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Release.ActiveCfg = Release|Win32
@@ -67,18 +83,18 @@ Global
 		{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.Build.0 = Debug|Win32
 		{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.ActiveCfg = Release|Win32
 		{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.Build.0 = Release|Win32
-		{58CCE183-6092-48FE-A4F7-BA0D3A792608}.Debug.ActiveCfg = Debug|Win32
-		{58CCE183-6092-48FE-A4F7-BA0D3A792608}.Debug.Build.0 = Debug|Win32
-		{58CCE183-6092-48FE-A4F7-BA0D3A792608}.Release.ActiveCfg = Release|Win32
-		{58CCE183-6092-48FE-A4F7-BA0D3A792608}.Release.Build.0 = Release|Win32
 		{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.ActiveCfg = Debug|Win32
 		{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.Build.0 = Debug|Win32
 		{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.ActiveCfg = Release|Win32
 		{5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.Build.0 = Release|Win32
-		{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Debug.ActiveCfg = Debug|Win32
-		{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Debug.Build.0 = Debug|Win32
-		{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Release.ActiveCfg = Release|Win32
-		{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Release.Build.0 = Release|Win32
+		{58CA17C5-A74F-9602-48FE-B06310DA7FA6}.Debug.ActiveCfg = Debug|Win32
+		{58CA17C5-A74F-9602-48FE-B06310DA7FA6}.Debug.Build.0 = Debug|Win32
+		{58CA17C5-A74F-9602-48FE-B06310DA7FA6}.Release.ActiveCfg = Release|Win32
+		{58CA17C5-A74F-9602-48FE-B06310DA7FA6}.Release.Build.0 = Release|Win32
+		{58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.ActiveCfg = Debug|Win32
+		{58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.Build.0 = Debug|Win32
+		{58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.ActiveCfg = Release|Win32
+		{58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 	EndGlobalSection
diff --git a/proj/vc7ide/container.vcproj b/proj/vc7ide/container.vcproj
index 500b5ca..7588d88 100644
--- a/proj/vc7ide/container.vcproj
+++ b/proj/vc7ide/container.vcproj
@@ -96,86 +96,7 @@
 	
 	
 		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
 			
@@ -209,15 +130,9 @@
 		
-			
-			
 			
 			
-			
-			
 			
 			
@@ -230,18 +145,12 @@
 			
 			
-			
-			
 			
 			
 			
 			
-			
-			
 			
 			
@@ -254,67 +163,154 @@
 			
 			
+			
+			
 			
 			
-			
-			
-			
-			
-			
-			
-			
-			
 			
 			
-			
-			
 			
 			
 		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
+		
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+				
+				
+				
+				
+				
+				
+			
+			
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+			
+		
 	
 	
 	
diff --git a/proj/vc7ide/list_ex.vcproj b/proj/vc7ide/list_test.vcproj
similarity index 100%
rename from proj/vc7ide/list_ex.vcproj
rename to proj/vc7ide/list_test.vcproj
diff --git a/proj/vc7ide/pair_test.vcproj b/proj/vc7ide/pair_test.vcproj
new file mode 100644
index 0000000..6f32b3e
--- /dev/null
+++ b/proj/vc7ide/pair_test.vcproj
@@ -0,0 +1,133 @@
+
+
+	
+		
+	
+	
+		
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+		
+		
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+		
+	
+	
+	
+	
+		
+			
+			
+		
+	
+	
+	
+
diff --git a/test/allocator_traits_test.cpp b/test/allocator_traits_test.cpp
new file mode 100644
index 0000000..ed109d4
--- /dev/null
+++ b/test/allocator_traits_test.cpp
@@ -0,0 +1,355 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2011. 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.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+template
+class SimpleAllocator
+{
+   bool allocate_called_;
+   bool deallocate_called_;
+   public:
+   typedef T value_type;
+
+   SimpleAllocator()
+      : allocate_called_(false)
+      , deallocate_called_(false)
+   {}
+
+   T* allocate(std::size_t)
+   {  allocate_called_ = true; return 0;  }
+
+   void deallocate(T*, std::size_t)
+   {  deallocate_called_ = true;  }
+
+   bool allocate_called() const
+   {  return allocate_called_;  }
+
+   bool deallocate_called() const
+   {  return deallocate_called_;  }
+};
+
+template
+class SimpleSmartPtr
+{
+   public:
+
+   SimpleSmartPtr()
+    : ptr_(0)
+   {}
+
+   SimpleSmartPtr(const SimpleSmartPtr &c)
+   {  this->ptr_ = c.ptr_; }
+
+   SimpleSmartPtr & operator=(const SimpleSmartPtr &c)
+   {  this->ptr_ = c.ptr_; }
+
+   typedef T* pointer;
+
+   private:
+   T *ptr_;
+};
+
+template
+class ComplexAllocator
+{
+   bool allocate_called_;
+   bool deallocate_called_;
+   bool allocate_hint_called_;
+   bool destroy_called_;
+   mutable bool max_size_called_;
+   mutable bool select_on_container_copy_construction_called_;
+   bool construct_called_;
+
+   public:
+   typedef T value_type;
+   typedef SimpleSmartPtr           pointer;
+   typedef SimpleSmartPtr     const_pointer;
+   typedef T &                         reference;
+   typedef const T &                   const_reference;
+   typedef SimpleSmartPtr        void_pointer;
+   typedef SimpleSmartPtr  const_void_pointer;
+   typedef signed short                difference_type;
+   typedef unsigned short              size_type;
+   typedef boost::true_type            propagate_on_container_copy_assignment;
+   typedef boost::true_type            propagate_on_container_move_assignment;
+   typedef boost::true_type            propagate_on_container_swap;
+
+   ComplexAllocator()
+      : allocate_called_(false)
+      , deallocate_called_(false)
+      , allocate_hint_called_(false)
+      , destroy_called_(false)
+      , max_size_called_(false)
+      , select_on_container_copy_construction_called_(false)
+      , construct_called_(false)
+   {}
+
+   pointer allocate(size_type)
+   {  allocate_called_ = true; return pointer();  }
+
+   void deallocate(pointer, size_type)
+   {  deallocate_called_ = true;  }
+
+   //optional
+   ComplexAllocator select_on_container_copy_construction() const
+   {  select_on_container_copy_construction_called_ = true; return *this;  }
+
+   pointer allocate(size_type n, const const_void_pointer &)
+   {  allocate_hint_called_ = true; return allocate(n);  }
+
+   template
+   void destroy(U*)
+   {  destroy_called_ = true;  }
+
+   size_type max_size() const
+   {  max_size_called_ = true; return size_type(size_type(0)-1);  }
+
+   #define BOOST_PP_LOCAL_MACRO(n)                                                              \
+   template                                \
+   void construct(U *p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _))            \
+   {                                                                                            \
+      construct_called_ = true;                                                                 \
+      ::new (p) U (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()
+
+   //getters
+   bool allocate_called() const
+   {  return allocate_called_;  }
+
+   bool deallocate_called() const
+   {  return deallocate_called_;  }
+
+   bool allocate_hint_called() const
+   {  return allocate_hint_called_;  }
+
+   bool destroy_called() const
+   {  return destroy_called_;  }
+
+   bool max_size_called() const
+   {  return max_size_called_;  }
+
+   bool select_on_container_copy_construction_called() const
+   {  return select_on_container_copy_construction_called_;  }
+
+   bool construct_called() const
+   {  return construct_called_;  }
+};
+
+class copymovable
+{
+   bool copymoveconstructed_;
+   bool moved_;
+
+   BOOST_COPYABLE_AND_MOVABLE(copymovable)
+
+   public:
+
+   copymovable(int, int, int)
+      : copymoveconstructed_(false), moved_(false)
+   {}
+
+   copymovable()
+      : copymoveconstructed_(false), moved_(false)
+   {}
+
+   copymovable(const copymovable &)
+      : copymoveconstructed_(true), moved_(false)
+   {}
+
+   copymovable(BOOST_RV_REF(copymovable))
+      : copymoveconstructed_(true), moved_(true)
+   {}
+
+   copymovable & operator=(BOOST_COPY_ASSIGN_REF(copymovable) ){ return *this; }
+   copymovable & operator=(BOOST_RV_REF(copymovable) ){ return *this; }
+
+   bool copymoveconstructed() const
+   {  return copymoveconstructed_;  }
+
+   bool moved() const
+   {  return moved_;  }
+};
+
+int main()
+{
+   //SimpleAllocator
+   BOOST_STATIC_ASSERT(( boost::is_same >::value_type, int>::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::pointer, int*>::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::const_pointer, const int*>::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::void_pointer, void*>::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::const_void_pointer, const void*>::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::difference_type, std::ptrdiff_t>::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::size_type, std::size_t>::value ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < SimpleAllocator >::propagate_on_container_copy_assignment::value == false ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < SimpleAllocator >::propagate_on_container_move_assignment::value == false ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < SimpleAllocator >::propagate_on_container_swap::value == false ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::rebind_traits::allocator_type
+                       , SimpleAllocator >::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::rebind_alloc::value_type
+                       , double >::value ));
+
+   //ComplexAllocator
+   BOOST_STATIC_ASSERT(( boost::is_same >::value_type, int>::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::pointer,  SimpleSmartPtr >::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::const_pointer, SimpleSmartPtr >::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::void_pointer, SimpleSmartPtr >::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::const_void_pointer, SimpleSmartPtr >::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::difference_type, signed short>::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::size_type, unsigned short>::value ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < ComplexAllocator >::propagate_on_container_copy_assignment::value == true ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < ComplexAllocator >::propagate_on_container_move_assignment::value == true ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < ComplexAllocator >::propagate_on_container_swap::value == true ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::rebind_traits::allocator_type
+                       , ComplexAllocator >::value ));
+   BOOST_STATIC_ASSERT(( boost::is_same >::rebind_alloc::value_type
+                       , double >::value ));
+
+   typedef ComplexAllocator CAlloc;
+   typedef SimpleAllocator SAlloc;
+   typedef boost::container::allocator_traits CAllocTraits;
+   typedef boost::container::allocator_traits SAllocTraits;
+   CAlloc c_alloc;
+   SAlloc s_alloc;
+
+   //allocate
+   CAllocTraits::allocate(c_alloc, 1);
+   if(!c_alloc.allocate_called()){
+      return 1;
+   }
+   SAllocTraits::allocate(s_alloc, 1);
+   if(!s_alloc.allocate_called()){
+      return 1;
+   }
+
+   //deallocate
+   CAllocTraits::deallocate(c_alloc, CAllocTraits::pointer(), 1);
+   if(!c_alloc.deallocate_called()){
+      return 1;
+   }
+   SAllocTraits::deallocate(s_alloc, SAllocTraits::pointer(), 1);
+   if(!s_alloc.deallocate_called()){
+      return 1;
+   }
+
+   //allocate with hint
+   CAllocTraits::allocate(c_alloc, 1, CAllocTraits::const_void_pointer());
+   if(!c_alloc.allocate_hint_called()){
+      return 1;
+   }
+   SAllocTraits::allocate(s_alloc, 1, SAllocTraits::const_void_pointer());
+
+   //destroy
+   float dummy;
+   CAllocTraits::destroy(c_alloc, &dummy);
+   if(!c_alloc.destroy_called()){
+      return 1;
+   }
+   SAllocTraits::destroy(s_alloc, &dummy);
+
+   //max_size
+   CAllocTraits::max_size(c_alloc);
+   if(!c_alloc.max_size_called()){
+      return 1;
+   }
+   SAllocTraits::max_size(s_alloc);
+
+   //select_on_container_copy_construction
+   CAllocTraits::select_on_container_copy_construction(c_alloc);
+   if(!c_alloc.select_on_container_copy_construction_called()){
+      return 1;
+   }
+   SAllocTraits::select_on_container_copy_construction(s_alloc);
+
+   //construct
+   {
+      copymovable c;
+      copymovable c2;
+      CAllocTraits::construct(c_alloc, &c, c2);
+      if(!c_alloc.construct_called() || !c.copymoveconstructed() || c.moved()){
+         return 1;
+      }
+   }
+   {
+      copymovable c;
+      copymovable c2;
+      CAllocTraits::construct(c_alloc, &c, ::boost::move(c2));
+      if(!c_alloc.construct_called() || !c.copymoveconstructed() || !c.moved()){
+         return 1;
+      }
+   }
+   {
+      copymovable c;
+      copymovable c2;
+      SAllocTraits::construct(s_alloc, &c, c2);
+      if(!c.copymoveconstructed() || c.moved()){
+         return 1;
+      }
+   }
+   {
+      copymovable c;
+      copymovable c2;
+      SAllocTraits::construct(s_alloc, &c, ::boost::move(c2));
+      if(!c.copymoveconstructed() || !c.moved()){
+         return 1;
+      }
+   }
+   {
+      copymovable c;
+      CAllocTraits::construct(c_alloc, &c, 0, 1, 2);
+      if(!c_alloc.construct_called() || c.copymoveconstructed() || c.moved()){
+         return 1;
+      }
+   }
+   {
+      copymovable c;
+      copymovable c2;
+      SAllocTraits::construct(s_alloc, &c, 0, 1, 2);
+      if(c.copymoveconstructed() || c.moved()){
+         return 1;
+      }
+   }
+
+   return 0;
+}
+#include 
diff --git a/test/check_equal_containers.hpp b/test/check_equal_containers.hpp
index ccdfa45..ad89e6b 100644
--- a/test/check_equal_containers.hpp
+++ b/test/check_equal_containers.hpp
@@ -8,8 +8,8 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
-#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINERS_HPP
-#define BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINERS_HPP
+#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
+#define BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
 
 #include 
 #include 
@@ -73,4 +73,4 @@ bool CheckEqualPairContainers(MyBoostCont *boostcont, MyStdCont *stdcont)
 
 #include 
 
-#endif //#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINERS_HPP
+#endif //#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
diff --git a/test/deque_test.cpp b/test/deque_test.cpp
index ad4b7ac..bc8bf9e 100644
--- a/test/deque_test.cpp
+++ b/test/deque_test.cpp
@@ -26,26 +26,39 @@
 #include 
 #include 
 #include "emplace_test.hpp"
+#include "propagate_allocator_test.hpp"
 #include "vector_test.hpp"
 
-
 using namespace boost::container;
 
+namespace boost {
+namespace container {
+
 //Explicit instantiation to detect compilation errors
+template class boost::container::deque
+ < test::movable_and_copyable_int
+ , test::simple_allocator >;
+
 template class boost::container::deque
  < test::movable_and_copyable_int
  , test::dummy_test_allocator >;
 
+template class boost::container::deque
+ < test::movable_and_copyable_int
+ , std::allocator >;
+
+}}
+
 //Function to check if both sets are equal
 template
-bool deque_copyable_only(V1 *, V2 *, containers_detail::false_type)
+bool deque_copyable_only(V1 *, V2 *, container_detail::false_type)
 {
    return true;
 }
 
 //Function to check if both sets are equal
 template
-bool deque_copyable_only(V1 *cntdeque, V2 *stddeque, containers_detail::true_type)
+bool deque_copyable_only(V1 *cntdeque, V2 *stddeque, container_detail::true_type)
 {
    typedef typename V1::value_type IntType;
    std::size_t size = cntdeque->size();
@@ -100,6 +113,10 @@ bool deque_copyable_only(V1 *cntdeque, V2 *stddeque, containers_detail::true_typ
 class recursive_deque
 {
 public:
+
+   recursive_deque & operator=(const recursive_deque &x)
+   {  this->deque_ = x.deque_;   return *this; }
+
    int id_;
    deque deque_;
 };
@@ -161,6 +178,7 @@ bool do_test()
 
       typename MyCntDeque::iterator it;
       typename MyCntDeque::const_iterator cit = it;
+      (void)cit;
 
       cntdeque->erase(cntdeque->begin()++);
       stddeque->erase(stddeque->begin()++);
@@ -212,7 +230,7 @@ bool do_test()
       }
 
       if(!deque_copyable_only(cntdeque, stddeque
-                     ,containers_detail::bool_::value>())){
+                     ,container_detail::bool_::value>())){
          return false;
       }
 
@@ -268,6 +286,21 @@ int main ()
    if(!do_test())
       return 1;
 
+   if(!do_test())
+      return 1;
+
+   if(!do_test())
+      return 1;
+
+   //Test non-copy-move operations
+   {
+      deque d;
+      d.emplace_back();
+      d.emplace_front(1);
+      d.resize(10);
+      d.resize(1);
+   }
+
    {
       typedef deque MyDeque;
       typedef deque MyMoveDeque;
@@ -289,6 +322,9 @@ int main ()
       < deque, Options>())
       return 1;
 
+   if(!boost::container::test::test_propagate_allocator())
+      return 1;
+
    return 0;
 }
 
diff --git a/test/dummy_test_allocator.hpp b/test/dummy_test_allocator.hpp
index e03255e..719d0ca 100644
--- a/test/dummy_test_allocator.hpp
+++ b/test/dummy_test_allocator.hpp
@@ -23,7 +23,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -37,34 +40,59 @@ namespace boost {
 namespace container {
 namespace test {
 
-//This allocator just allows two allocations. The first one will return 
-//mp_buffer + m_offset configured in the constructor. The second one
-//will return mp_buffer.
+//Very simple version 1 allocator
+template
+class simple_allocator
+{
+   public:
+   typedef T value_type;
+
+   simple_allocator()
+   {}
+
+   template
+   simple_allocator(const simple_allocator &)
+   {}
+
+   T* allocate(std::size_t n)
+   {  return (T*)::new char[sizeof(T)*n];  }
+
+   void deallocate(T*p, std::size_t)
+   { delete[] ((char*)p);}
+
+   friend bool operator==(const simple_allocator &, const simple_allocator &)
+   {  return true;  }
+
+   friend bool operator!=(const simple_allocator &, const simple_allocator &)
+   {  return false;  }
+};
+
+//Version 2 allocator with rebind
 template
 class dummy_test_allocator 
 {
  private:
-   typedef dummy_test_allocator self_t;
+   typedef dummy_test_allocator  self_t;
    typedef void *                   aux_pointer_t;
    typedef const void *             cvoid_ptr;
 
-   template
-   dummy_test_allocator& operator=(const dummy_test_allocator&);
-
-   dummy_test_allocator& operator=(const dummy_test_allocator&);
-
    public:
    typedef T                                    value_type;
    typedef T *                                  pointer;
    typedef const T *                            const_pointer;
-   typedef typename containers_detail::add_reference
+   typedef typename container_detail::add_reference
                      ::type         reference;
-   typedef typename containers_detail::add_reference
+   typedef typename container_detail::add_reference
                      ::type   const_reference;
    typedef std::size_t                          size_type;
    typedef std::ptrdiff_t                       difference_type;
 
-//   typedef boost::container::version_type   version;
+   typedef container_detail::basic_multiallocation_chain
+                                                  multialloc_cached_counted;
+   typedef boost::container::container_detail::transform_multiallocation_chain
+                  multiallocation_chain;
+
+   typedef boost::container::container_detail::version_type   version;
 
    template
    struct rebind
@@ -115,7 +143,7 @@ class dummy_test_allocator
                          size_type, 
                          size_type,
                          size_type &, const pointer & = 0)
-   {  return std::pair(pointer(0), true); }
+   {  return std::pair(pointer(), true); }
 
    //!Returns maximum the number of objects the previously allocated memory
    //!pointed by p can hold.
@@ -126,26 +154,198 @@ class dummy_test_allocator
    //!must be deallocated only with deallocate_one().
    //!Throws boost::container::bad_alloc if there is no enough memory
    pointer allocate_one()
-   {  return pointer(0);  }
+   {  return pointer();  }
 
    //!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(const pointer &)
    {}
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   multiallocation_chain allocate_individual(size_type)
+   {  return multiallocation_chain(); }
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   void deallocate_individual(multiallocation_chain)
+   {}
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   void deallocate_many(multiallocation_chain)
+   {}
 };
 
 //!Equality test for same type of dummy_test_allocator
 template inline
 bool operator==(const dummy_test_allocator  &, 
                 const dummy_test_allocator  &)
-{  return false; }
+{  return true; }
 
 //!Inequality test for same type of dummy_test_allocator
 template inline
 bool operator!=(const dummy_test_allocator  &, 
                 const dummy_test_allocator  &)
-{  return true; }
+{  return false; }
+
+
+template< class T
+        , bool PropagateOnContCopyAssign 
+        , bool PropagateOnContMoveAssign
+        , bool PropagateOnContSwap
+        , bool CopyOnPropagateOnContSwap
+        >
+class propagation_test_allocator
+{
+   BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator)
+
+   public:
+   typedef T value_type;
+   typedef boost::container::container_detail::bool_
+      propagate_on_container_copy_assignment;
+   typedef boost::container::container_detail::bool_
+      propagate_on_container_move_assignment;
+   typedef boost::container::container_detail::bool_
+      propagate_on_container_swap;
+
+   template
+   struct rebind
+   {  typedef propagation_test_allocator
+         < T2
+         , PropagateOnContCopyAssign
+         , PropagateOnContMoveAssign
+         , PropagateOnContSwap
+         , CopyOnPropagateOnContSwap>   other;
+   };
+
+   propagation_test_allocator select_on_container_copy_construction() const
+   {  return CopyOnPropagateOnContSwap ? propagation_test_allocator(*this) : propagation_test_allocator();  }
+
+   explicit propagation_test_allocator()
+      : id_(unique_id_++)
+      , ctr_copies_(0)
+      , ctr_moves_(0)
+      , assign_copies_(0)
+      , assign_moves_(0)
+      , swaps_(0)
+   {}
+
+   propagation_test_allocator(const propagation_test_allocator &x)
+      : id_(x.id_)
+      , ctr_copies_(x.ctr_copies_+1)
+      , ctr_moves_(x.ctr_moves_)
+      , assign_copies_(x.assign_copies_)
+      , assign_moves_(x.assign_moves_)
+      , swaps_(x.swaps_)
+   {}
+
+   template
+   propagation_test_allocator(const propagation_test_allocator
+                                       < U
+                                       , PropagateOnContCopyAssign
+                                       , PropagateOnContMoveAssign
+                                       , PropagateOnContSwap
+                                       , CopyOnPropagateOnContSwap> &x)
+      : id_(x.id_)
+      , ctr_copies_(0)
+      , ctr_moves_(0)
+      , assign_copies_(0)
+      , assign_moves_(0)
+      , swaps_(0)
+   {}
+
+   propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) x)
+      : id_(x.id_)
+      , ctr_copies_(x.ctr_copies_)
+      , ctr_moves_(x.ctr_moves_ + 1)
+      , assign_copies_(x.assign_copies_)
+      , assign_moves_(x.assign_moves_)
+      , swaps_(x.swaps_)
+   {}
+
+   propagation_test_allocator &operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator) x)
+   {
+      id_ = x.id_;
+      ctr_copies_ = x.ctr_copies_;
+      ctr_moves_ = x.ctr_moves_;
+      assign_copies_ = x.assign_copies_+1;
+      assign_moves_ = x.assign_moves_;
+      swaps_ = x.swaps_;
+      return *this;
+   }
+
+   propagation_test_allocator &operator=(BOOST_RV_REF(propagation_test_allocator) x)
+   {
+      id_ = x.id_;
+      ctr_copies_ = x.ctr_copies_;
+      ctr_moves_ = x.ctr_moves_;
+      assign_copies_ = x.assign_copies_;
+      assign_moves_ = x.assign_moves_+1;
+      swaps_ = x.swaps_;
+      return *this;
+   }
+
+   static void reset_unique_id()
+   {  unique_id_ = 0;  }
+
+   T* allocate(std::size_t n)
+   {  return (T*)::new char[sizeof(T)*n];  }
+
+   void deallocate(T*p, std::size_t)
+   { delete[] ((char*)p);}
+
+   friend bool operator==(const propagation_test_allocator &, const propagation_test_allocator &)
+   {  return true;  }
+
+   friend bool operator!=(const propagation_test_allocator &, const propagation_test_allocator &)
+   {  return false;  }
+
+   friend void swap(propagation_test_allocator &l, propagation_test_allocator &r)
+   {
+      ++l.swaps_; ++r.swaps_;
+      container_detail::do_swap(l.id_, r.id_);
+      container_detail::do_swap(l.ctr_copies_, r.ctr_copies_);
+      container_detail::do_swap(l.ctr_moves_, r.ctr_moves_);
+      container_detail::do_swap(l.assign_copies_, r.assign_copies_);
+      container_detail::do_swap(l.assign_moves_, r.assign_moves_);
+      container_detail::do_swap(l.swaps_, r.swaps_);
+   }
+
+   unsigned int id_;
+   unsigned int ctr_copies_;
+   unsigned int ctr_moves_;
+   unsigned int assign_copies_;
+   unsigned int assign_moves_;
+   unsigned int swaps_;
+   static unsigned unique_id_;
+};
+
+template< class T
+        , bool PropagateOnContCopyAssign 
+        , bool PropagateOnContMoveAssign
+        , bool PropagateOnContSwap
+        , bool CopyOnPropagateOnContSwap
+        >
+unsigned int propagation_test_allocator< T
+                                       , PropagateOnContCopyAssign
+                                       , PropagateOnContMoveAssign
+                                       , PropagateOnContSwap
+                                       , CopyOnPropagateOnContSwap>::unique_id_ = 0;
+
 
 }  //namespace test {
 }  //namespace container {
diff --git a/test/emplace_test.hpp b/test/emplace_test.hpp
index 3cae3f8..ff93659 100644
--- a/test/emplace_test.hpp
+++ b/test/emplace_test.hpp
@@ -157,7 +157,7 @@ static EmplaceIntPair * expected_pair = initialize_emplace_int_pair();
 
 
 template
-bool test_emplace_back(containers_detail::true_)
+bool test_emplace_back(container_detail::true_)
 {
    std::cout << "Starting test_emplace_back." << std::endl << "  Class: "
       << typeid(Container).name() << std::endl;
@@ -194,11 +194,11 @@ bool test_emplace_back(containers_detail::true_)
 }
 
 template
-bool test_emplace_back(containers_detail::false_)
+bool test_emplace_back(container_detail::false_)
 {  return true;   }
 
 template
-bool test_emplace_front(containers_detail::true_)
+bool test_emplace_front(container_detail::true_)
 {
    std::cout << "Starting test_emplace_front." << std::endl << "  Class: "
       << typeid(Container).name() << std::endl;
@@ -234,11 +234,11 @@ bool test_emplace_front(containers_detail::true_)
 }
 
 template
-bool test_emplace_front(containers_detail::false_)
+bool test_emplace_front(container_detail::false_)
 {  return true;   }
 
 template
-bool test_emplace_before(containers_detail::true_)
+bool test_emplace_before(container_detail::true_)
 {
    std::cout << "Starting test_emplace_before." << std::endl << "  Class: "
       << typeid(Container).name() << std::endl;
@@ -309,11 +309,11 @@ bool test_emplace_before(containers_detail::true_)
 }
 
 template
-bool test_emplace_before(containers_detail::false_)
+bool test_emplace_before(container_detail::false_)
 {  return true;   }
 
 template
-bool test_emplace_after(containers_detail::true_)
+bool test_emplace_after(container_detail::true_)
 {
    std::cout << "Starting test_emplace_after." << std::endl << "  Class: "
       << typeid(Container).name() << std::endl;
@@ -383,11 +383,11 @@ bool test_emplace_after(containers_detail::true_)
 }
 
 template
-bool test_emplace_after(containers_detail::false_)
+bool test_emplace_after(container_detail::false_)
 {  return true;   }
 
 template
-bool test_emplace_assoc(containers_detail::true_)
+bool test_emplace_assoc(container_detail::true_)
 {
    std::cout << "Starting test_emplace_assoc." << std::endl << "  Class: "
       << typeid(Container).name() << std::endl;
@@ -423,11 +423,11 @@ bool test_emplace_assoc(containers_detail::true_)
 }
 
 template
-bool test_emplace_assoc(containers_detail::false_)
+bool test_emplace_assoc(container_detail::false_)
 {  return true;   }
 
 template
-bool test_emplace_hint(containers_detail::true_)
+bool test_emplace_hint(container_detail::true_)
 {
    std::cout << "Starting test_emplace_hint." << std::endl << "  Class: "
       << typeid(Container).name() << std::endl;
@@ -466,11 +466,11 @@ bool test_emplace_hint(containers_detail::true_)
 }
 
 template
-bool test_emplace_hint(containers_detail::false_)
+bool test_emplace_hint(container_detail::false_)
 {  return true;   }
 
 template
-bool test_emplace_assoc_pair(containers_detail::true_)
+bool test_emplace_assoc_pair(container_detail::true_)
 {
    std::cout << "Starting test_emplace_assoc_pair." << std::endl << "  Class: "
       << typeid(Container).name() << std::endl;
@@ -478,15 +478,9 @@ bool test_emplace_assoc_pair(containers_detail::true_)
    new(&expected_pair[0].first) EmplaceInt();
    new(&expected_pair[0].second) EmplaceInt();
    new(&expected_pair[1].first) EmplaceInt(1);
-   new(&expected_pair[1].second) EmplaceInt();
+   new(&expected_pair[1].second) EmplaceInt(1);
    new(&expected_pair[2].first) EmplaceInt(2);
    new(&expected_pair[2].second) EmplaceInt(2);
-   new(&expected_pair[3].first) EmplaceInt(3);
-   new(&expected_pair[3].second) EmplaceInt(2, 3);
-   new(&expected_pair[4].first) EmplaceInt(4);
-   new(&expected_pair[4].second) EmplaceInt(2, 3, 4);
-   new(&expected_pair[5].first) EmplaceInt(5);
-   new(&expected_pair[5].second) EmplaceInt(2, 3, 4, 5);
    {
       Container c;
       c.emplace();
@@ -494,7 +488,7 @@ bool test_emplace_assoc_pair(containers_detail::true_)
          std::cout << "Error after c.emplace();\n";
          return false;
       }
-      c.emplace(1);
+      c.emplace(1, 1);
       if(!test_expected_container(c, &expected_pair[0], 2)){
          std::cout << "Error after c.emplace(1);\n";
          return false;
@@ -504,31 +498,16 @@ bool test_emplace_assoc_pair(containers_detail::true_)
          std::cout << "Error after c.emplace(2, 2);\n";
          return false;
       }
-      c.emplace(3, 2, 3);
-      if(!test_expected_container(c, &expected_pair[0], 4)){
-         std::cout << "Error after c.emplace(3, 2, 3);\n";
-         return false;
-      }
-      c.emplace(4, 2, 3, 4);
-      if(!test_expected_container(c, &expected_pair[0], 5)){
-         std::cout << "Error after c.emplace(4, 2, 3, 4);\n";
-         return false;
-      }
-      c.emplace(5, 2, 3, 4, 5);
-      if(!test_expected_container(c, &expected_pair[0], 6)){
-         std::cout << "Error after c.emplace(5, 2, 3, 4, 5);\n";
-         return false;
-      }
    }
    return true;
 }
 
 template
-bool test_emplace_assoc_pair(containers_detail::false_)
+bool test_emplace_assoc_pair(container_detail::false_)
 {  return true;   }
 
 template
-bool test_emplace_hint_pair(containers_detail::true_)
+bool test_emplace_hint_pair(container_detail::true_)
 {
    std::cout << "Starting test_emplace_hint_pair." << std::endl << "  Class: "
       << typeid(Container).name() << std::endl;
@@ -536,15 +515,9 @@ bool test_emplace_hint_pair(containers_detail::true_)
    new(&expected_pair[0].first) EmplaceInt();
    new(&expected_pair[0].second) EmplaceInt();
    new(&expected_pair[1].first) EmplaceInt(1);
-   new(&expected_pair[1].second) EmplaceInt();
+   new(&expected_pair[1].second) EmplaceInt(1);
    new(&expected_pair[2].first) EmplaceInt(2);
    new(&expected_pair[2].second) EmplaceInt(2);
-   new(&expected_pair[3].first) EmplaceInt(3);
-   new(&expected_pair[3].second) EmplaceInt(2, 3);
-   new(&expected_pair[4].first) EmplaceInt(4);
-   new(&expected_pair[4].second) EmplaceInt(2, 3, 4);
-   new(&expected_pair[5].first) EmplaceInt(5);
-   new(&expected_pair[5].second) EmplaceInt(2, 3, 4, 5);
    {
       Container c;
       typename Container::const_iterator it;
@@ -553,7 +526,7 @@ bool test_emplace_hint_pair(containers_detail::true_)
          std::cout << "Error after c.emplace(1);\n";
          return false;
       }
-      it = c.emplace_hint(it, 1);
+      it = c.emplace_hint(it, 1, 1);
       if(!test_expected_container(c, &expected_pair[0], 2)){
          std::cout << "Error after c.emplace(it, 1);\n";
          return false;
@@ -563,44 +536,29 @@ bool test_emplace_hint_pair(containers_detail::true_)
          std::cout << "Error after c.emplace(it, 2, 2);\n";
          return false;
       }
-      it = c.emplace_hint(it, 3, 2, 3);
-      if(!test_expected_container(c, &expected_pair[0], 4)){
-         std::cout << "Error after c.emplace(it, 3, 2, 3);\n";
-         return false;
-      }
-      it = c.emplace_hint(it, 4, 2, 3, 4);
-      if(!test_expected_container(c, &expected_pair[0], 5)){
-         std::cout << "Error after c.emplace(it, 4, 2, 3, 4);\n";
-         return false;
-      }
-      it = c.emplace_hint(it, 5, 2, 3, 4, 5);
-      if(!test_expected_container(c, &expected_pair[0], 6)){
-         std::cout << "Error after c.emplace(it, 5, 2, 3, 4, 5);\n";
-         return false;
-      }
    }
    return true;
 }
 
 template
-bool test_emplace_hint_pair(containers_detail::false_)
+bool test_emplace_hint_pair(container_detail::false_)
 {  return true;   }
 
 template 
 struct emplace_active
 {
    static const bool value = (0 != (O & Mask));
-   typedef containers_detail::bool_ type;
+   typedef container_detail::bool_ type;
    operator type() const{  return type(); }
 };
 
 template
 bool test_emplace()
 {
-//   if(!test_emplace_back(emplace_active()))
-//      return false;
+   if(!test_emplace_back(emplace_active()))
+      return false;
    if(!test_emplace_front(emplace_active()))
-      return false;/*
+      return false;
    if(!test_emplace_before(emplace_active()))
       return false;
    if(!test_emplace_after(emplace_active()))
@@ -612,7 +570,7 @@ bool test_emplace()
    if(!test_emplace_assoc_pair(emplace_active()))
       return false;
    if(!test_emplace_hint_pair(emplace_active()))
-      return false;*/
+      return false;
    return true;
 }
 
diff --git a/test/expand_bwd_test_allocator.hpp b/test/expand_bwd_test_allocator.hpp
index 1b690e3..67aea9d 100644
--- a/test/expand_bwd_test_allocator.hpp
+++ b/test/expand_bwd_test_allocator.hpp
@@ -56,14 +56,14 @@ class expand_bwd_test_allocator
    typedef T                                    value_type;
    typedef T *                                  pointer;
    typedef const T *                            const_pointer;
-   typedef typename containers_detail::add_reference
+   typedef typename container_detail::add_reference
                      ::type         reference;
-   typedef typename containers_detail::add_reference
+   typedef typename container_detail::add_reference
                      ::type   const_reference;
    typedef std::size_t                          size_type;
    typedef std::ptrdiff_t                       difference_type;
 
-   typedef boost::container::containers_detail::version_type   version;
+   typedef boost::container::container_detail::version_type   version;
 
    template
    struct rebind
@@ -109,9 +109,9 @@ class expand_bwd_test_allocator
 
    friend void swap(self_t &alloc1, self_t &alloc2)
    {  
-      containers_detail::do_swap(alloc1.mp_buffer, alloc2.mp_buffer);
-      containers_detail::do_swap(alloc1.m_size,    alloc2.m_size);
-      containers_detail::do_swap(alloc1.m_offset,  alloc2.m_offset);
+      container_detail::do_swap(alloc1.mp_buffer, alloc2.mp_buffer);
+      container_detail::do_swap(alloc1.m_size,    alloc2.m_size);
+      container_detail::do_swap(alloc1.m_offset,  alloc2.m_offset);
    }
 
    //Experimental version 2 expand_bwd_test_allocator functions
diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp
index e8f9173..4203704 100644
--- a/test/flat_tree_test.cpp
+++ b/test/flat_tree_test.cpp
@@ -17,10 +17,106 @@
 #include "movable_int.hpp"
 #include "set_test.hpp"
 #include "map_test.hpp"
+#include "propagate_allocator_test.hpp"
 #include "emplace_test.hpp"
 
 using namespace boost::container;
 
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+//flat_map
+template class flat_map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , test::dummy_test_allocator
+      < std::pair >
+   >;
+
+template class flat_map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , test::simple_allocator
+      < std::pair >
+   >;
+
+template class flat_map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , std::allocator
+      < std::pair >
+   >;
+
+//flat_multimap
+template class flat_multimap
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , test::dummy_test_allocator
+      < std::pair >
+   >;
+
+template class flat_multimap
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , test::simple_allocator
+      < std::pair >
+   >;
+
+template class flat_multimap
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , std::allocator
+      < std::pair >
+   >;
+//flat_set
+template class flat_set
+   < test::movable_and_copyable_int
+   , std::less
+   , test::dummy_test_allocator
+   >;
+
+template class flat_set
+   < test::movable_and_copyable_int
+   , std::less
+   , test::simple_allocator
+   >;
+
+template class flat_set
+   < test::movable_and_copyable_int
+   , std::less
+   , std::allocator
+   >;
+
+//flat_multiset
+template class flat_multiset
+   < test::movable_and_copyable_int
+   , std::less
+   , test::dummy_test_allocator
+   >;
+
+template class flat_multiset
+   < test::movable_and_copyable_int
+   , std::less
+   , test::simple_allocator
+   >;
+
+template class flat_multiset
+   < test::movable_and_copyable_int
+   , std::less
+   , std::allocator
+   >;
+
+}} //boost::container
+
+
 //Alias allocator type
 typedef std::allocator allocator_t;
 typedef std::allocator 
@@ -84,7 +180,6 @@ typedef flat_multimap                        MyCopyBoostMultiMap;
 
 
-
 //Test recursive structures
 class recursive_flat_set
 {
@@ -178,6 +273,36 @@ void test_move()
    move_assign.swap(original);
 }
 
+template
+class flat_tree_propagate_test_wrapper
+   : public container_detail::flat_tree, std::less, A>
+{
+   BOOST_COPYABLE_AND_MOVABLE(flat_tree_propagate_test_wrapper)
+   typedef container_detail::flat_tree, std::less, A> Base;
+   public:
+   flat_tree_propagate_test_wrapper()
+      : Base()
+   {}
+
+   flat_tree_propagate_test_wrapper(const flat_tree_propagate_test_wrapper &x)
+      : Base(x)
+   {}
+
+   flat_tree_propagate_test_wrapper(BOOST_RV_REF(flat_tree_propagate_test_wrapper) x)
+      : Base(boost::move(static_cast(x)))
+   {}
+
+   flat_tree_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(flat_tree_propagate_test_wrapper) x)
+   {  this->Base::operator=(x);  return *this; }
+
+   flat_tree_propagate_test_wrapper &operator=(BOOST_RV_REF(flat_tree_propagate_test_wrapper) x)
+   {  this->Base::operator=(boost::move(static_cast(x)));  return *this; }
+
+   void swap(flat_tree_propagate_test_wrapper &x)
+   {  this->Base::swap(x);  }
+};
+
+
 int main()
 {
    using namespace boost::container::test;
@@ -272,13 +397,13 @@ int main()
       return 1;
    }
 
-//   if (0 != map_test<
-//                  MyMovableBoostMap
-//                  ,MyStdMap
-//                  ,MyMovableBoostMultiMap
-//                  ,MyStdMultiMap>()){
-//      return 1;
-//   }
+   if (0 != map_test<
+                  MyMovableBoostMap
+                  ,MyStdMap
+                  ,MyMovableBoostMultiMap
+                  ,MyStdMultiMap>()){
+      return 1;
+   }
 
    if (0 != map_test<
                   MyMoveCopyBoostMap
@@ -319,14 +444,17 @@ int main()
    const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC);
    const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR);
 
-//   if(!boost::container::test::test_emplace, MapOptions>())
-//      return 1;
+   if(!boost::container::test::test_emplace, MapOptions>())
+      return 1;
    if(!boost::container::test::test_emplace, MapOptions>())
       return 1;
    if(!boost::container::test::test_emplace, SetOptions>())
       return 1;
    if(!boost::container::test::test_emplace, SetOptions>())
       return 1;
+   if(!boost::container::test::test_propagate_allocator())
+      return 1;
+
    return 0;
 }
 
diff --git a/test/heap_allocator_v1.hpp b/test/heap_allocator_v1.hpp
index 1e572c3..32b46b5 100644
--- a/test/heap_allocator_v1.hpp
+++ b/test/heap_allocator_v1.hpp
@@ -18,7 +18,7 @@
 #include 
 #include 
 
-#include 
+#include 
 
 #include 
 #include 
diff --git a/test/list_test.cpp b/test/list_test.cpp
index 9127ee1..602f547 100644
--- a/test/list_test.cpp
+++ b/test/list_test.cpp
@@ -11,15 +11,29 @@
 #include 
 #include 
 #include "dummy_test_allocator.hpp"
+#include 
 #include "movable_int.hpp"
 #include "list_test.hpp"
+#include "propagate_allocator_test.hpp"
 #include "emplace_test.hpp"
 
 using namespace boost::container;
 
+namespace boost {
+namespace container {
+
 //Explicit instantiation to detect compilation errors
+template class boost::container::list >;
+
 template class boost::container::list >;
+
+template class boost::container::list >;
+
+}}
+
 typedef list MyList;
 
 typedef list MyMoveList;
@@ -72,6 +86,9 @@ int main ()
    if(!boost::container::test::test_emplace, Options>())
       return 1;
 
+   if(!boost::container::test::test_propagate_allocator())
+      return 1;
+
    return 0;
 }
 
diff --git a/test/list_test.hpp b/test/list_test.hpp
index 121c287..c248231 100644
--- a/test/list_test.hpp
+++ b/test/list_test.hpp
@@ -26,14 +26,14 @@ namespace container {
 namespace test{
 
 template
-bool list_copyable_only(V1 *, V2 *, boost::container::containers_detail::false_type)
+bool list_copyable_only(V1 *, V2 *, boost::container::container_detail::false_type)
 {
    return true;
 }
 
 //Function to check if both sets are equal
 template
-bool list_copyable_only(V1 *boostlist, V2 *stdlist, boost::container::containers_detail::true_type)
+bool list_copyable_only(V1 *boostlist, V2 *stdlist, boost::container::container_detail::true_type)
 {
    typedef typename V1::value_type IntType;
    boostlist->insert(boostlist->end(), 50, IntType(1));
@@ -289,7 +289,7 @@ int list_test (bool copied_allocators_equal = true)
          }
 
          if(!list_copyable_only(boostlist, stdlist
-                        ,containers_detail::bool_::value>())){
+                        ,container_detail::bool_::value>())){
             return 1;
          }
       }
diff --git a/test/map_test.hpp b/test/map_test.hpp
index f41acba..5eee229 100644
--- a/test/map_test.hpp
+++ b/test/map_test.hpp
@@ -38,7 +38,7 @@ template         IntPairType;
+   typedef container_detail::pair         IntPairType;
    typedef typename MyStdMap::value_type  StdPairType;
    const int max = 100;
 
@@ -101,6 +101,9 @@ int map_test ()
             IntType i2(i);
             new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
          }
+         if(!CheckEqualContainers(boostmap2, stdmap2)) return 1;
+         if(!CheckEqualContainers(boostmultimap2, stdmultimap2)) return 1;
+
 /*
          MyBoostMap *boostmap3 = new MyBoostMap 
                ( ordered_unique_range
@@ -122,6 +125,23 @@ int map_test ()
             return 1;
          }
 */
+         IntType i0(0);
+         boostmap2->erase(i0);
+         boostmultimap2->erase(i0);
+         stdmap2->erase(0);
+         stdmultimap2->erase(0);
+         {
+            IntType i0(0);
+            IntType i1(1);
+            (*boostmap2)[::boost::move(i0)] = ::boost::move(i1);
+         }
+         {
+            IntType i1(1);
+            (*boostmap2)[IntType(0)] = ::boost::move(i1);
+         }
+         (*stdmap2)[0] = 1;
+         if(!CheckEqualContainers(boostmap2, stdmap2)) return 1;
+
          delete boostmap2;
          delete boostmultimap2;
          delete stdmap2;
@@ -158,6 +178,7 @@ int map_test ()
 
          typename MyBoostMap::iterator it;
          typename MyBoostMap::const_iterator cit = it;
+         (void)cit;
 
          boostmap->erase(boostmap->begin()++);
          stdmap->erase(stdmap->begin()++);
@@ -449,7 +470,7 @@ template         IntPairType;
+   typedef container_detail::pair         IntPairType;
    typedef typename MyStdMap::value_type  StdPairType;
 
    const int max = 100;
diff --git a/test/movable_int.hpp b/test/movable_int.hpp
index 37bf71d..599dbbb 100644
--- a/test/movable_int.hpp
+++ b/test/movable_int.hpp
@@ -221,6 +221,45 @@ struct is_copyable
    static const bool value = true;
 };
 
+class non_copymovable_int
+{
+   non_copymovable_int(const non_copymovable_int& mmi);
+   non_copymovable_int & operator= (const non_copymovable_int &mi);
+
+   public:
+   non_copymovable_int()
+      :  m_int(0)
+   {}
+
+   explicit non_copymovable_int(int a)
+      :  m_int(a)
+   {}
+
+   bool operator ==(const non_copymovable_int &mi) const
+   {  return this->m_int == mi.m_int;   }
+
+   bool operator !=(const non_copymovable_int &mi) const
+   {  return this->m_int != mi.m_int;   }
+
+   bool operator <(const non_copymovable_int &mi) const
+   {  return this->m_int < mi.m_int;   }
+
+   bool operator <=(const non_copymovable_int &mi) const
+   {  return this->m_int <= mi.m_int;   }
+
+   bool operator >=(const non_copymovable_int &mi) const
+   {  return this->m_int >= mi.m_int;   }
+
+   bool operator >(const non_copymovable_int &mi) const
+   {  return this->m_int > mi.m_int;   }
+
+   int get_int() const
+   {  return m_int;  }
+
+   private:
+   int m_int;
+};
+
 }  //namespace test {
 }  //namespace container {
 }  //namespace boost {
diff --git a/test/pair_test.cpp b/test/pair_test.cpp
new file mode 100644
index 0000000..c44b9d5
--- /dev/null
+++ b/test/pair_test.cpp
@@ -0,0 +1,54 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2011. 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.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include 
+#include 
+#include "movable_int.hpp"
+#include "emplace_test.hpp"
+#include
+
+//non_copymovable_int
+//copyable_int
+//movable_int
+//movable_and_copyable_int
+
+
+using namespace ::boost::container;
+
+int main ()
+{
+   {
+      container_detail::pair p1;
+      container_detail::pair p2;
+      container_detail::pair p3;
+      container_detail::pair p4;
+   }
+   {  //Constructible from two values
+      container_detail::pair p1(1, 2);
+      container_detail::pair p2(1, 2);
+      container_detail::pair p3(1, 2);
+      container_detail::pair p4(1, 2);
+   }
+
+   {  //Constructible from internal types
+      container_detail::pair p2(test::copyable_int(1), test::copyable_int(2));
+      {
+         test::movable_int a(1), b(2);
+         container_detail::pair p3(::boost::move(a), ::boost::move(b));
+      }
+      {
+         test::movable_and_copyable_int a(1), b(2);
+         container_detail::pair p4(::boost::move(a), ::boost::move(b));
+      }
+   }
+   //piecewise_construct missing...
+   return 0;
+}
+
+#include 
diff --git a/test/propagate_allocator_test.hpp b/test/propagate_allocator_test.hpp
new file mode 100644
index 0000000..8901d77
--- /dev/null
+++ b/test/propagate_allocator_test.hpp
@@ -0,0 +1,181 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008. 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_PROPAGATE_ALLOCATOR_TEST_HPP
+#define BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
+
+#include 
+#include 
+#include "dummy_test_allocator.hpp"
+
+#include 
+
+namespace boost{
+namespace container {
+namespace test{
+
+template class ContainerWrapper>
+bool test_propagate_allocator()
+{
+   {
+      typedef propagation_test_allocator  AlwaysPropagate;
+      typedef ContainerWrapper                   PropagateCont;
+
+      //////////////////////////////////////////
+      //Test AlwaysPropagate allocator propagation
+      //////////////////////////////////////////
+      AlwaysPropagate::reset_unique_id();
+
+      //default constructor
+      PropagateCont c;
+      BOOST_TEST (c.get_stored_allocator().id_ == 0);
+      BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
+      BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+      BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+
+      //copy constructor
+      PropagateCont c2(c);
+      //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler).
+      //For allocators that copy in select_on_container_copy_construction, at least we must have a copy
+      unsigned int ctr_copies = c2.get_stored_allocator().ctr_copies_;
+      unsigned int ctr_moves = c2.get_stored_allocator().ctr_moves_;
+      BOOST_TEST (c2.get_stored_allocator().id_ == 0);
+      BOOST_TEST (ctr_copies > 0);
+      BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
+      BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+
+      //move constructor
+      PropagateCont c3(boost::move(c2));
+      BOOST_TEST (c3.get_stored_allocator().id_ == 0);
+      BOOST_TEST (c3.get_stored_allocator().ctr_copies_ == ctr_copies);
+      BOOST_TEST (c3.get_stored_allocator().ctr_moves_ > ctr_moves);
+      ctr_moves = c3.get_stored_allocator().ctr_moves_;
+      BOOST_TEST (ctr_moves > 0);
+      BOOST_TEST (c3.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c3.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c3.get_stored_allocator().swaps_ == 0);
+
+      //copy assign
+      c2 = c3;
+      unsigned int assign_copies = c2.get_stored_allocator().assign_copies_;
+      BOOST_TEST (c2.get_stored_allocator().id_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == ctr_copies);
+      BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == ctr_moves);
+      BOOST_TEST (assign_copies == 1);
+      BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+
+      //move assign
+      c = boost::move(c2);
+      unsigned int assign_moves = c.get_stored_allocator().assign_moves_;
+      BOOST_TEST (c.get_stored_allocator().id_ == 0);
+      BOOST_TEST (c.get_stored_allocator().ctr_copies_    == ctr_copies);
+      BOOST_TEST (c.get_stored_allocator().ctr_moves_     == ctr_moves);
+      BOOST_TEST (c.get_stored_allocator().assign_copies_ == assign_copies);
+      BOOST_TEST (assign_moves == 1);
+      BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+
+      //swap
+      c.get_stored_allocator().id_ = 999;
+      c.swap(c2);
+      unsigned int swaps = c2.get_stored_allocator().swaps_;
+      BOOST_TEST (c2.get_stored_allocator().id_ == 999);
+      BOOST_TEST (c2.get_stored_allocator().ctr_copies_    == ctr_copies);
+      BOOST_TEST (c2.get_stored_allocator().ctr_moves_     == ctr_moves);
+      BOOST_TEST (c2.get_stored_allocator().assign_copies_ == assign_copies);
+      BOOST_TEST (c2.get_stored_allocator().assign_moves_  == assign_moves);
+      BOOST_TEST (swaps == 1);
+   }
+
+   //////////////////////////////////////////
+   //Test NeverPropagate allocator propagation
+   //////////////////////////////////////////
+   {
+      typedef propagation_test_allocator NeverPropagate;
+      typedef ContainerWrapper                       NoPropagateCont;
+      NeverPropagate::reset_unique_id();
+
+      //default constructor
+      NoPropagateCont c;
+      BOOST_TEST (c.get_stored_allocator().id_ == 0);
+      BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
+      BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+      BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+
+      //copy constructor
+      //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler)
+      //For allocators that don't copy in select_on_container_copy_construction we must have a default
+      //construction
+      NoPropagateCont c2(c);
+      unsigned int ctr_copies = c2.get_stored_allocator().ctr_copies_;
+      unsigned int ctr_moves = c2.get_stored_allocator().ctr_moves_;
+      BOOST_TEST (c2.get_stored_allocator().id_ == 1);
+      BOOST_TEST (ctr_copies >= 0);
+      BOOST_TEST (ctr_moves >= 0);
+      BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+
+      //move constructor
+      NoPropagateCont c3(boost::move(c2));
+      BOOST_TEST (c3.get_stored_allocator().id_ == 1);
+      BOOST_TEST (c3.get_stored_allocator().ctr_copies_ == ctr_copies);
+      BOOST_TEST (c3.get_stored_allocator().ctr_moves_ > ctr_moves);
+      unsigned int ctr_moves2 = ctr_moves;
+      ctr_moves = c3.get_stored_allocator().ctr_moves_;
+      BOOST_TEST (c3.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c3.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c3.get_stored_allocator().swaps_ == 0);
+
+      //copy assign
+      c2 = c3;
+      BOOST_TEST (c2.get_stored_allocator().id_ == 1);
+      BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == ctr_copies);
+      BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == ctr_moves2);
+      BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+
+      //move assign
+      c = boost::move(c2);
+      BOOST_TEST (c.get_stored_allocator().id_ == 0);
+      BOOST_TEST (c.get_stored_allocator().ctr_copies_    == 0);
+      BOOST_TEST (c.get_stored_allocator().ctr_moves_     == 0);
+      BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+
+      //swap
+      c.get_stored_allocator().id_ = 999;
+      c2.swap(c);
+      BOOST_TEST (c2.get_stored_allocator().id_ == 1);
+      BOOST_TEST (c.get_stored_allocator().id_ == 999);
+      BOOST_TEST (c2.get_stored_allocator().ctr_copies_    == ctr_copies);
+      BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == ctr_moves2);
+      BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+   }
+
+   return report_errors() == 0;
+}
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include 
+
+#endif   //#ifndef BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
diff --git a/test/set_test.hpp b/test/set_test.hpp
index e4061eb..5dd6a2a 100644
--- a/test/set_test.hpp
+++ b/test/set_test.hpp
@@ -145,6 +145,7 @@ int set_test ()
 
    typename MyBoostSet::iterator it;
    typename MyBoostSet::const_iterator cit = it;
+   (void)cit;
 
    boostset->erase(boostset->begin()++);
    stdset->erase(stdset->begin()++);
diff --git a/test/slist_test.cpp b/test/slist_test.cpp
index e18f0bb..fb9f28f 100644
--- a/test/slist_test.cpp
+++ b/test/slist_test.cpp
@@ -9,17 +9,29 @@
 //////////////////////////////////////////////////////////////////////////////
 #include 
 #include 
+#include 
 #include "dummy_test_allocator.hpp"
 #include "movable_int.hpp"
 #include "list_test.hpp"
+#include "propagate_allocator_test.hpp"
 #include "emplace_test.hpp"
 
 using namespace boost::container;
 
+namespace boost {
+namespace container {
+
 //Explicit instantiation to detect compilation errors
+template class boost::container::slist >;
+
 template class boost::container::slist >;
 
+template class boost::container::slist >;
+}}
+
 typedef slist MyList;
 typedef slist MyMoveList;
 typedef slist MyCopyMoveList;
@@ -76,6 +88,9 @@ int main ()
    if(!boost::container::test::test_emplace
       < slist, Options>())
       return 1;
+
+   if(!boost::container::test::test_propagate_allocator())
+      return 1;
 }
 
 #include 
diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp
index bf42978..edcd404 100644
--- a/test/stable_vector_test.cpp
+++ b/test/stable_vector_test.cpp
@@ -21,13 +21,25 @@
 #include "expand_bwd_test_allocator.hpp"
 #include "expand_bwd_test_template.hpp"
 #include "dummy_test_allocator.hpp"
+#include "propagate_allocator_test.hpp"
 #include "vector_test.hpp"
 
 using namespace boost::container;
 
+namespace boost {
+namespace container {
+
 //Explicit instantiation to detect compilation errors
-//template class stable_vector >;
+template class stable_vector >;
+
+template class stable_vector >;
+
+template class stable_vector >;
+
+}}
 
 class recursive_vector
 {
@@ -58,6 +70,14 @@ int main()
       move_assign = boost::move(move_ctor);
       move_assign.swap(original);
    }
+
+   //Test non-copy-move operations
+   {
+      stable_vector sv;
+      sv.emplace_back();
+      sv.resize(10);
+      sv.resize(1);
+   }
    typedef stable_vector MyVector;
    typedef stable_vector MyMoveVector;
    typedef stable_vector MyCopyMoveVector;
@@ -80,6 +100,9 @@ int main()
       < stable_vector, Options>())
       return 1;
 
+   if(!boost::container::test::test_propagate_allocator())
+      return 1;
+
    return 0;
 }
 
diff --git a/test/string_test.cpp b/test/string_test.cpp
index 8c873ce..3799d4a 100644
--- a/test/string_test.cpp
+++ b/test/string_test.cpp
@@ -22,6 +22,7 @@
 #include "check_equal_containers.hpp"
 #include "expand_bwd_test_allocator.hpp"
 #include "expand_bwd_test_template.hpp"
+#include "propagate_allocator_test.hpp"
 
 using namespace boost::container;
 
@@ -32,13 +33,23 @@ typedef test::dummy_test_allocator              DummyWCharAllocator;
 typedef basic_string, DummyWCharAllocator> DummyWString;
 typedef test::dummy_test_allocator         DummyWStringAllocator;
 
+namespace boost {
+namespace container {
+
 //Explicit instantiations of container::basic_string
-template class basic_string, DummyCharAllocator>;
+template class basic_string, DummyCharAllocator>;
 template class basic_string, DummyWCharAllocator>;
+template class basic_string, test::simple_allocator >;
+template class basic_string, test::simple_allocator >;
+template class basic_string, std::allocator >;
+template class basic_string, std::allocator >;
+
 //Explicit instantiation of container::vectors of container::strings
 template class vector;
 template class vector;
 
+}}
+
 struct StringEqual
 {
    template
@@ -60,10 +71,64 @@ bool CheckEqualStringVector(StrVector1 *strvect1, StrVector2 *strvect2)
                      strvect2->begin(), comp);
 }
 
+template
+struct string_literals;
+
+template<>
+struct string_literals
+{
+   static const char *String()
+      {  return "String";  }
+   static const char *Prefix()
+      {  return "Prefix";  }
+   static const char *Suffix()
+      {  return "Suffix";  }
+   static const char *LongString()
+      {  return "LongLongLongLongLongLongLongLongLongLongLongLongLongString";  }
+
+   static void sprintf_number(char *buf, int number)
+   {
+      std::sprintf(buf, "%i", number);
+   }
+};
+
+template<>
+struct string_literals
+{
+   static const wchar_t *String()
+      {  return L"String";  }
+   static const wchar_t *Prefix()
+      {  return L"Prefix";  }
+   static const wchar_t *Suffix()
+      {  return L"Suffix";  }
+   static const wchar_t *LongString()
+      {  return L"LongLongLongLongLongLongLongLongLongLongLongLongLongString";  }
+
+   static void sprintf_number(wchar_t *buffer, unsigned int number)
+   {
+      //For compilers without wsprintf, print it backwards
+      const wchar_t *digits = L"0123456789";
+      wchar_t *buf = buffer;
+
+      while(1){
+         int rem = number % 10;
+         number  = number / 10;
+
+         *buf = digits[rem];
+         ++buf;
+         if(!number){
+            *buf = 0;
+            break;
+         }
+      }
+
+   }
+};
+
 template
 int string_test()
 {
-   typedef std::string        StdString;
+   typedef std::basic_string StdString;
    typedef vector  StdStringVector;
    typedef basic_string BoostString;
    typedef vector BoostStringVector;
@@ -81,9 +146,9 @@ int string_test()
 
       //First, push back
       for(int i = 0; i < MaxSize; ++i){
-         auxBoostString = "String";
-         auxStdString = "String";
-         std::sprintf(buffer, "%i", i);
+         auxBoostString = string_literals::String();
+         auxStdString = string_literals::String();
+         string_literals::sprintf_number(buffer, i);
          auxBoostString += buffer;
          auxStdString += buffer;
          boostStringVect->push_back(auxBoostString);
@@ -96,9 +161,9 @@ int string_test()
 
       //Now push back moving 
       for(int i = 0; i < MaxSize; ++i){
-         auxBoostString = "String";
-         auxStdString = "String";
-         std::sprintf(buffer, "%i", i);
+         auxBoostString = string_literals::String();
+         auxStdString = string_literals::String();
+         string_literals::sprintf_number(buffer, i);
          auxBoostString += buffer;
          auxStdString += buffer;
          boostStringVect->push_back(boost::move(auxBoostString));
@@ -111,9 +176,9 @@ int string_test()
 
       //push front
       for(int i = 0; i < MaxSize; ++i){
-         auxBoostString = "String";
-         auxStdString = "String";
-         std::sprintf(buffer, "%i", i);
+         auxBoostString = string_literals::String();
+         auxStdString = string_literals::String();
+         string_literals::sprintf_number(buffer, i);
          auxBoostString += buffer;
          auxStdString += buffer;
          boostStringVect->insert(boostStringVect->begin(), auxBoostString);
@@ -126,9 +191,9 @@ int string_test()
 
       //Now push front moving 
       for(int i = 0; i < MaxSize; ++i){
-         auxBoostString = "String";
-         auxStdString = "String";
-         std::sprintf(buffer, "%i", i);
+         auxBoostString = string_literals::String();
+         auxStdString = string_literals::String();
+         string_literals::sprintf_number(buffer, i);
          auxBoostString += buffer;
          auxStdString += buffer;
          boostStringVect->insert(boostStringVect->begin(), boost::move(auxBoostString));
@@ -142,8 +207,8 @@ int string_test()
       //Now test long and short representation swapping
 
       //Short first
-      auxBoostString = "String";
-      auxStdString = "String";
+      auxBoostString = string_literals::String();
+      auxStdString = string_literals::String();
       BoostString boost_swapper;
       StdString std_swapper;
       boost_swapper.swap(auxBoostString);
@@ -177,8 +242,8 @@ int string_test()
          return 1;
 
       //Long string
-      auxBoostString = "LongLongLongLongLongLongLongLongLongLongLongLongLongString";
-      auxStdString   = "LongLongLongLongLongLongLongLongLongLongLongLongLongString";
+      auxBoostString = string_literals::LongString();
+      auxStdString   = string_literals::LongString();
       boost_swapper = BoostString();
       std_swapper = StdString();
       boost_swapper.swap(auxBoostString);
@@ -208,9 +273,9 @@ int string_test()
       std::sort(stdStringVect->begin(), stdStringVect->end());
       if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
 
-      const CharType prefix []    = "Prefix";
-      const int  prefix_size  = sizeof(prefix)/sizeof(prefix[0])-1;
-      const CharType sufix []     = "Suffix";
+      const CharType *prefix    = string_literals::Prefix();
+      const int  prefix_size    = std::char_traits::length(prefix);
+      const CharType *sufix      = string_literals::Suffix();
 
       for(int i = 0; i < MaxSize; ++i){
          (*boostStringVect)[i].append(sufix);
@@ -247,10 +312,10 @@ int string_test()
       for(int i = 0; i < MaxSize; ++i){
          (*boostStringVect)[i].replace((*boostStringVect)[i].begin(), 
                                     (*boostStringVect)[i].end(),
-                                    "String");
+                                    string_literals::String());
          (*stdStringVect)[i].replace((*stdStringVect)[i].begin(), 
                                     (*stdStringVect)[i].end(),
-                                    "String");
+                                    string_literals::String());
       }
 
       if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
@@ -261,6 +326,80 @@ int string_test()
                            stdStringVect->end());
       if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
 
+      //Check addition
+      {
+         typedef std::basic_string StdString;
+         typedef basic_string BoostString;
+         
+         BoostString bs2 = string_literals::String();
+         StdString   ss2 = string_literals::String();
+         BoostString bs3 = string_literals::Suffix();
+         StdString   ss3 = string_literals::Suffix();
+         BoostString bs4 = bs2 + bs3;
+         StdString   ss4 = ss2 + ss3;
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs4 = bs2 + BoostString();
+         ss4 = ss2 + StdString();
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs4 = BoostString() + bs2;
+         ss4 = StdString() + ss2;
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs4 = BoostString() + boost::move(bs2);
+         ss4 = StdString() + boost::move(ss2);
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals::String();
+         ss2 = string_literals::String();
+         bs4 = boost::move(bs2) + BoostString();
+         ss4 = boost::move(ss2) + StdString();
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals::String();
+         ss2 = string_literals::String();
+         bs4 = string_literals::Prefix() + boost::move(bs2);
+         ss4 = string_literals::Prefix() + boost::move(ss2);
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals::String();
+         ss2 = string_literals::String();
+         bs4 = boost::move(bs2) + string_literals::Suffix();
+         ss4 = boost::move(ss2) + string_literals::Suffix();
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals::String();
+         ss2 = string_literals::String();
+         bs4 = string_literals::Prefix() + bs2;
+         ss4 = string_literals::Prefix() + ss2;
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals::String();
+         ss2 = string_literals::String();
+         bs4 = bs2 + string_literals::Suffix();
+         ss4 = ss2 + string_literals::Suffix();
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+      }
+
       //When done, delete vector
       delete boostStringVect;
       delete stdStringVect;
@@ -278,15 +417,51 @@ bool test_expand_bwd()
    return  test::test_all_expand_bwd();
 }
 
+template
+class string_propagate_test_wrapper
+   : public basic_string, A>
+{
+   BOOST_COPYABLE_AND_MOVABLE(string_propagate_test_wrapper)
+   typedef basic_string, A> Base;
+   public:
+   string_propagate_test_wrapper()
+      : Base()
+   {}
+
+   string_propagate_test_wrapper(const string_propagate_test_wrapper &x)
+      : Base(x)
+   {}
+
+   string_propagate_test_wrapper(BOOST_RV_REF(string_propagate_test_wrapper) x)
+      : Base(boost::move(static_cast(x)))
+   {}
+
+   string_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(string_propagate_test_wrapper) x)
+   {  this->Base::operator=(x);  return *this; }
+
+   string_propagate_test_wrapper &operator=(BOOST_RV_REF(string_propagate_test_wrapper) x)
+   {  this->Base::operator=(boost::move(static_cast(x)));  return *this; }
+
+   void swap(string_propagate_test_wrapper &x)
+   {  this->Base::swap(x);  }
+};
+
 int main()
 {
    if(string_test()){
       return 1;
    }
 
+   if(string_test()){
+      return 1;
+   }
+
    if(!test_expand_bwd())
       return 1;
 
+   if(!boost::container::test::test_propagate_allocator())
+      return 1;
+
    return 0;
 }
 
diff --git a/test/tree_test.cpp b/test/tree_test.cpp
index 0df3ac4..0717cce 100644
--- a/test/tree_test.cpp
+++ b/test/tree_test.cpp
@@ -16,6 +16,7 @@
 #include "dummy_test_allocator.hpp"
 #include "set_test.hpp"
 #include "map_test.hpp"
+#include "propagate_allocator_test.hpp"
 #include "emplace_test.hpp"
 
 using namespace boost::container;
@@ -49,10 +50,109 @@ typedef map                          MyCopyBoostMap;
 typedef multimap                     MyCopyBoostMultiMap;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+//map
+template class map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , test::dummy_test_allocator
+      < std::pair >
+   >;
+
+template class map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , test::simple_allocator
+      < std::pair >
+   >;
+
+template class map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , std::allocator
+      < std::pair >
+   >;
+
+//multimap
+template class multimap
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , test::dummy_test_allocator
+      < std::pair >
+   >;
+
+template class multimap
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , test::simple_allocator
+      < std::pair >
+   >;
+
+template class multimap
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less
+   , std::allocator
+      < std::pair >
+   >;
+
+//set
+template class set
+   < test::movable_and_copyable_int
+   , std::less
+   , test::dummy_test_allocator
+   >;
+
+template class set
+   < test::movable_and_copyable_int
+   , std::less
+   , test::simple_allocator
+   >;
+
+template class set
+   < test::movable_and_copyable_int
+   , std::less
+   , std::allocator
+   >;
+
+//multiset
+template class multiset
+   < test::movable_and_copyable_int
+   , std::less
+   , test::dummy_test_allocator
+   >;
+
+template class multiset
+   < test::movable_and_copyable_int
+   , std::less
+   , test::simple_allocator
+   >;
+
+template class multiset
+   < test::movable_and_copyable_int
+   , std::less
+   , std::allocator
+   >;
+
+}} //boost::container
+
 //Test recursive structures
 class recursive_set
 {
 public:
+   recursive_set & operator=(const recursive_set &x)
+   {  id_ = x.id_;  set_ = x.set_; return *this; }
+
    int id_;
    set set_;
    friend bool operator< (const recursive_set &a, const recursive_set &b)
@@ -62,6 +162,9 @@ public:
 class recursive_map
 {
    public:
+   recursive_map & operator=(const recursive_map &x)
+   {  id_ = x.id_;  map_ = x.map_; return *this;  }
+
    int id_;
    map map_;
    friend bool operator< (const recursive_map &a, const recursive_map &b)
@@ -71,7 +174,10 @@ class recursive_map
 //Test recursive structures
 class recursive_multiset
 {
-public:
+   public:
+   recursive_multiset & operator=(const recursive_multiset &x)
+   {  id_ = x.id_;  multiset_ = x.multiset_; return *this;  }
+
    int id_;
    multiset multiset_;
    friend bool operator< (const recursive_multiset &a, const recursive_multiset &b)
@@ -80,7 +186,10 @@ public:
 
 class recursive_multimap
 {
-public:
+   public:
+   recursive_multimap & operator=(const recursive_multimap &x)
+   {  id_ = x.id_;  multimap_ = x.multimap_; return *this;  }
+
    int id_;
    multimap multimap_;
    friend bool operator< (const recursive_multimap &a, const recursive_multimap &b)
@@ -98,6 +207,35 @@ void test_move()
    move_assign.swap(original);
 }
 
+template
+class tree_propagate_test_wrapper
+   : public container_detail::rbtree, std::less, A>
+{
+   BOOST_COPYABLE_AND_MOVABLE(tree_propagate_test_wrapper)
+   typedef container_detail::rbtree, std::less, A> Base;
+   public:
+   tree_propagate_test_wrapper()
+      : Base()
+   {}
+
+   tree_propagate_test_wrapper(const tree_propagate_test_wrapper &x)
+      : Base(x)
+   {}
+
+   tree_propagate_test_wrapper(BOOST_RV_REF(tree_propagate_test_wrapper) x)
+      : Base(boost::move(static_cast(x)))
+   {}
+
+   tree_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(tree_propagate_test_wrapper) x)
+   {  this->Base::operator=(x);  return *this; }
+
+   tree_propagate_test_wrapper &operator=(BOOST_RV_REF(tree_propagate_test_wrapper) x)
+   {  this->Base::operator=(boost::move(static_cast(x)));  return *this; }
+
+   void swap(tree_propagate_test_wrapper &x)
+   {  this->Base::swap(x);  }
+};
+
 int main ()
 {
    //Recursive container instantiation
@@ -180,13 +318,12 @@ int main ()
       return 1;
    }
 
-//   if (0 != test::map_test()){
-//      return 1;
-//   }
+   if (0 != test::map_test()){
+      return 1;
+   }
 
    if (0 != test::map_test, MapOptions>())
       return 1;
+   if(!boost::container::test::test_propagate_allocator())
+      return 1;
 
    return 0;
 }
diff --git a/test/vector_test.cpp b/test/vector_test.cpp
index 9bdc584..3be90ae 100644
--- a/test/vector_test.cpp
+++ b/test/vector_test.cpp
@@ -7,7 +7,6 @@
 // See http://www.boost.org/libs/container for documentation.
 //
 //////////////////////////////////////////////////////////////////////////////
-
 #include 
 #include 
 #include 
@@ -16,19 +15,32 @@
 #include 
 
 #include 
+#include 
 #include "check_equal_containers.hpp"
 #include "movable_int.hpp"
 #include "expand_bwd_test_allocator.hpp"
 #include "expand_bwd_test_template.hpp"
 #include "dummy_test_allocator.hpp"
+#include "propagate_allocator_test.hpp"
 #include "vector_test.hpp"
 
 using namespace boost::container;
 
+namespace boost {
+namespace container {
+
 //Explicit instantiation to detect compilation errors
+template class boost::container::vector >;
+
 template class boost::container::vector >;
 
+template class boost::container::vector >;
+
+}}
+
 int test_expand_bwd()
 {
    //Now test all back insertion possibilities
@@ -81,7 +93,6 @@ enum Test
    zero, one, two, three, four, five, six
 };
 
-
 int main()
 {
    recursive_vector_test();
@@ -99,7 +110,6 @@ int main()
    typedef vector MyCopyVector;
    typedef vector MyEnumVector;
 
-
    if(test::vector_test())
       return 1;
    if(test::vector_test())
@@ -122,6 +132,9 @@ int main()
       < vector, Options>())
       return 1;
 
+   if(!boost::container::test::test_propagate_allocator())
+      return 1;
+  
    return 0;
 }
 #include 
diff --git a/test/vector_test.hpp b/test/vector_test.hpp
index c57700e..4b6d7b7 100644
--- a/test/vector_test.hpp
+++ b/test/vector_test.hpp
@@ -30,14 +30,14 @@ namespace container {
 namespace test{
 
 template
-bool vector_copyable_only(V1 *, V2 *, boost::container::containers_detail::false_type)
+bool vector_copyable_only(V1 *, V2 *, boost::container::container_detail::false_type)
 {
    return true;
 }
 
 //Function to check if both sets are equal
 template
-bool vector_copyable_only(V1 *boostvector, V2 *stdvector, boost::container::containers_detail::true_type)
+bool vector_copyable_only(V1 *boostvector, V2 *stdvector, boost::container::container_detail::true_type)
 {
    typedef typename V1::value_type IntType;
    std::size_t size = boostvector->size();
@@ -111,6 +111,7 @@ int vector_test()
          typename MyBoostVector::iterator boostit(boostvector->begin());
          typename MyStdVector::iterator stdit(stdvector->begin());
          typename MyBoostVector::const_iterator cboostit = boostit;
+         (void)cboostit;
          ++boostit; ++stdit;
          boostvector->erase(boostit);
          stdvector->erase(stdit);
@@ -183,7 +184,7 @@ int vector_test()
          if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
 
          if(!vector_copyable_only(boostvector, stdvector
-                        ,containers_detail::bool_::value>())){
+                        ,container_detail::bool_::value>())){
             return 1;
          }
 

From 336a1cc472012c7efa476f6b53d01e57acaeb90c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= 
Date: Fri, 23 Dec 2011 11:47:56 +0000
Subject: [PATCH 09/14] Bug #6205

[SVN r76113]
---
 include/boost/container/deque.hpp         |  2 --
 include/boost/container/flat_map.hpp      | 38 +++++++++++------------
 include/boost/container/flat_set.hpp      | 30 +++++++++---------
 include/boost/container/list.hpp          |  2 --
 include/boost/container/map.hpp           |  2 --
 include/boost/container/set.hpp           |  2 --
 include/boost/container/slist.hpp         |  2 --
 include/boost/container/stable_vector.hpp |  2 --
 include/boost/container/vector.hpp        |  2 --
 9 files changed, 32 insertions(+), 50 deletions(-)

diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp
index d77398b..a2baf04 100644
--- a/include/boost/container/deque.hpp
+++ b/include/boost/container/deque.hpp
@@ -985,8 +985,6 @@ class deque : protected deque_base
    }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type()
-   //!   allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp
index bb35ce2..bec26e3 100644
--- a/include/boost/container/flat_map.hpp
+++ b/include/boost/container/flat_map.hpp
@@ -436,7 +436,6 @@ class flat_map
    }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type() allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
@@ -454,7 +453,7 @@ class flat_map
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    std::pair insert(const value_type& x) 
       { return container_detail::force >(
          m_flat_tree.insert_unique(container_detail::force(x))); }
@@ -469,7 +468,7 @@ class flat_map
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    std::pair insert(BOOST_RV_REF(value_type) x) 
    {  return container_detail::force >(
       m_flat_tree.insert_unique(boost::move(container_detail::force(x)))); }
@@ -484,7 +483,7 @@ class flat_map
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    std::pair insert(BOOST_RV_REF(impl_value_type) x) 
    {
       return container_detail::force >
@@ -501,7 +500,7 @@ class flat_map
    //! Complexity: Logarithmic search time (constant if x is inserted
    //!   right before p) plus insertion linear to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(const_iterator position, const value_type& x)
       { return container_detail::force_copy(
          m_flat_tree.insert_unique(container_detail::force(position), container_detail::force(x))); }
@@ -514,7 +513,7 @@ class flat_map
    //! Complexity: Logarithmic search time (constant if x is inserted
    //!   right before p) plus insertion linear to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(const_iterator position, BOOST_RV_REF(value_type) x)
       { return container_detail::force_copy(
          m_flat_tree.insert_unique(container_detail::force(position), boost::move(container_detail::force(x)))); }
@@ -527,7 +526,7 @@ class flat_map
    //! Complexity: Logarithmic search time (constant if x is inserted
    //!   right before p) plus insertion linear to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(const_iterator position, BOOST_RV_REF(impl_value_type) x)
    {
       return container_detail::force_copy(
@@ -542,7 +541,7 @@ class flat_map
    //! Complexity: At most N log(size()+N) (N is the distance from first to last)
    //!   search time plus N*size() insertion time.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    void insert(InputIterator first, InputIterator last) 
    {  m_flat_tree.insert_unique(first, last);  }
@@ -560,7 +559,7 @@ class flat_map
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    iterator emplace(Args&&... args)
    {  return container_detail::force_copy(m_flat_tree.emplace_unique(boost::forward(args)...)); }
@@ -576,7 +575,7 @@ class flat_map
    //! Complexity: Logarithmic search time (constant if x is inserted
    //!   right before p) plus insertion linear to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {  return container_detail::force_copy(m_flat_tree.emplace_hint_unique(container_detail::force(hint), boost::forward(args)...)); }
@@ -1103,7 +1102,6 @@ class flat_multimap
       { return m_flat_tree.max_size(); }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type() allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
@@ -1117,7 +1115,7 @@ class flat_multimap
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(const value_type& x) 
       { return container_detail::force_copy(m_flat_tree.insert_equal(container_detail::force(x))); }
 
@@ -1127,7 +1125,7 @@ class flat_multimap
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(BOOST_RV_REF(value_type) x) 
    { return container_detail::force_copy(m_flat_tree.insert_equal(boost::move(x))); }
 
@@ -1137,7 +1135,7 @@ class flat_multimap
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(BOOST_RV_REF(impl_value_type) x) 
       { return container_detail::force_copy(m_flat_tree.insert_equal(boost::move(x))); }
 
@@ -1151,7 +1149,7 @@ class flat_multimap
    //!   is to be inserted before p) plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(const_iterator position, const value_type& x) 
       { return container_detail::force_copy(m_flat_tree.insert_equal(container_detail::force(position), container_detail::force(x))); }
 
@@ -1165,7 +1163,7 @@ class flat_multimap
    //!   is to be inserted before p) plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(const_iterator position, BOOST_RV_REF(value_type) x) 
    {
       return container_detail::force_copy
@@ -1183,7 +1181,7 @@ class flat_multimap
    //!   is to be inserted before p) plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(const_iterator position, BOOST_RV_REF(impl_value_type) x) 
    {
       return container_detail::force_copy(
@@ -1197,7 +1195,7 @@ class flat_multimap
    //! Complexity: At most N log(size()+N) (N is the distance from first to last)
    //!   search time plus N*size() insertion time.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    void insert(InputIterator first, InputIterator last) 
       {  m_flat_tree.insert_equal(first, last); }
@@ -1211,7 +1209,7 @@ class flat_multimap
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    iterator emplace(Args&&... args)
    {  return container_detail::force_copy(m_flat_tree.emplace_equal(boost::forward(args)...)); }
@@ -1227,7 +1225,7 @@ class flat_multimap
    //!   is to be inserted before p) plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {
diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp
index 07e1f1f..9d40bdd 100644
--- a/include/boost/container/flat_set.hpp
+++ b/include/boost/container/flat_set.hpp
@@ -324,7 +324,6 @@ class flat_set
       { return m_flat_tree.max_size(); }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type() allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
@@ -342,7 +341,7 @@ class flat_set
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    std::pair insert(insert_const_ref_type x) 
    {  return priv_insert(x); }
 
@@ -365,7 +364,7 @@ class flat_set
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    std::pair insert(BOOST_RV_REF(value_type) x) 
    {  return m_flat_tree.insert_unique(boost::move(x));  }
 
@@ -379,7 +378,7 @@ class flat_set
    //! Complexity: Logarithmic search time (constant if x is inserted
    //!   right before p) plus insertion linear to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(const_iterator p, insert_const_ref_type x) 
    {  return priv_insert(p, x); }
 
@@ -400,7 +399,7 @@ class flat_set
    //! Complexity: Logarithmic search time (constant if x is inserted
    //!   right before p) plus insertion linear to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: 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)); }
 
@@ -412,7 +411,7 @@ class flat_set
    //! Complexity: At most N log(size()+N) (N is the distance from first to last)
    //!   search time plus N*size() insertion time.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    void insert(InputIterator first, InputIterator last) 
       {  m_flat_tree.insert_unique(first, last);  }
@@ -430,7 +429,7 @@ class flat_set
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    iterator emplace(Args&&... args)
    {  return m_flat_tree.emplace_unique(boost::forward(args)...); }
@@ -446,7 +445,7 @@ class flat_set
    //! Complexity: Logarithmic search time (constant if x is inserted
    //!   right before p) plus insertion linear to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {  return m_flat_tree.emplace_hint_unique(hint, boost::forward(args)...); }
@@ -929,7 +928,6 @@ class flat_multiset
       { return m_flat_tree.max_size(); }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type() allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
@@ -943,7 +941,7 @@ class flat_multiset
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(insert_const_ref_type x) 
    {  return priv_insert(x); }
 
@@ -962,7 +960,7 @@ class flat_multiset
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: 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));   }
 
@@ -975,7 +973,7 @@ class flat_multiset
    //! Complexity: Logarithmic search time (constant if x is inserted
    //!   right before p) plus insertion linear to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    iterator insert(const_iterator p, insert_const_ref_type x) 
    {  return priv_insert(p, x); }
 
@@ -997,7 +995,7 @@ class flat_multiset
    //! Complexity: Logarithmic search time (constant if x is inserted
    //!   right before p) plus insertion linear to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: 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));  }
 
@@ -1008,7 +1006,7 @@ class flat_multiset
    //! Complexity: At most N log(size()+N) (N is the distance from first to last)
    //!   search time plus N*size() insertion time.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    void insert(InputIterator first, InputIterator last) 
       {  m_flat_tree.insert_equal(first, last);  }
@@ -1022,7 +1020,7 @@ class flat_multiset
    //! Complexity: Logarithmic search time plus linear insertion
    //!   to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    iterator emplace(Args&&... args)
    {  return m_flat_tree.emplace_equal(boost::forward(args)...); }
@@ -1037,7 +1035,7 @@ class flat_multiset
    //! Complexity: Logarithmic search time (constant if x is inserted
    //!   right before p) plus insertion linear to the elements with bigger keys than x.
    //!
-   //! Note: If an element it's inserted it might invalidate elements.
+   //! Note: If an element is inserted it might invalidate elements.
    template 
    iterator emplace_hint(const_iterator hint, Args&&... args)
    {  return m_flat_tree.emplace_hint_equal(hint, boost::forward(args)...); }
diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp
index 03ba7f1..6df999b 100644
--- a/include/boost/container/list.hpp
+++ b/include/boost/container/list.hpp
@@ -701,8 +701,6 @@ class list
    }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type()
-   //!   allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp
index 63717d9..f77dfa8 100644
--- a/include/boost/container/map.hpp
+++ b/include/boost/container/map.hpp
@@ -376,7 +376,6 @@ class map
    }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type() allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
@@ -1019,7 +1018,6 @@ class multimap
    { return m_tree.max_size(); }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type() allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp
index 485f64d..3cf22b5 100644
--- a/include/boost/container/set.hpp
+++ b/include/boost/container/set.hpp
@@ -317,7 +317,6 @@ class set
    { return m_tree.max_size(); }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type() allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
@@ -884,7 +883,6 @@ class multiset
    { return m_tree.max_size(); }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type() allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp
index ffa538e..a3c6dd9 100644
--- a/include/boost/container/slist.hpp
+++ b/include/boost/container/slist.hpp
@@ -596,8 +596,6 @@ class slist
    {  return !this->size();   }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type()
-   //!   allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp
index 2d25fbe..f4ea541 100644
--- a/include/boost/container/stable_vector.hpp
+++ b/include/boost/container/stable_vector.hpp
@@ -1226,8 +1226,6 @@ class stable_vector
    {   return priv_erase(first, last, alloc_version());  }
 
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type()
-   //!   allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!
diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp
index 7a2aa4f..d7b2978 100644
--- a/include/boost/container/vector.hpp
+++ b/include/boost/container/vector.hpp
@@ -1080,8 +1080,6 @@ class vector : private container_detail::vector_alloc_holder
    #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
   
    //! Effects: Swaps the contents of *this and x.
-   //!   If this->allocator_type() != x.allocator_type()
-   //!   allocators are also swapped.
    //!
    //! Throws: Nothing.
    //!

From ae4468fccc5ebcfdf8b551e371781bf75be4b2e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= 
Date: Fri, 23 Dec 2011 12:00:27 +0000
Subject: [PATCH 10/14] Bug #6287

[SVN r76114]
---
 include/boost/container/container_fwd.hpp | 22 ----------------------
 1 file changed, 22 deletions(-)

diff --git a/include/boost/container/container_fwd.hpp b/include/boost/container/container_fwd.hpp
index b58ca8e..1bd460e 100644
--- a/include/boost/container/container_fwd.hpp
+++ b/include/boost/container/container_fwd.hpp
@@ -32,32 +32,10 @@ namespace bi = boost::intrusive;
 
 }}}
 
-#ifndef _LIBCPP_VERSION
-
-namespace std {
-
-template 
-class allocator;
-
-template 
-struct less;
-
-template 
-struct pair;
-
-template  
-struct char_traits;
-
-}  //namespace std {
-
-#else 
-
 #include  
 #include  
 #include  
 #include  
- 
-#endif
 
 /// @endcond
 

From 3b02e445745d57919b5419a6dc223a6bc56d795f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= 
Date: Sat, 24 Dec 2011 18:57:27 +0000
Subject: [PATCH 11/14] Bug #4383

[SVN r76143]
---
 include/boost/container/container_fwd.hpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/boost/container/container_fwd.hpp b/include/boost/container/container_fwd.hpp
index 1bd460e..da325e4 100644
--- a/include/boost/container/container_fwd.hpp
+++ b/include/boost/container/container_fwd.hpp
@@ -35,7 +35,8 @@ namespace bi = boost::intrusive;
 #include  
 #include  
 #include  
-#include  
+#include 
+#include 
 
 /// @endcond
 

From ab3e0c2bbf549c41c578bd85151bfb501e8d58f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= 
Date: Mon, 26 Dec 2011 11:07:21 +0000
Subject: [PATCH 12/14] Fixed compilation error for some GCC versions

[SVN r76167]
---
 include/boost/container/deque.hpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp
index a2baf04..d3b4732 100644
--- a/include/boost/container/deque.hpp
+++ b/include/boost/container/deque.hpp
@@ -379,7 +379,7 @@ class deque_base
       :  members_(a)
    { this->priv_initialize_map(num_elements); }
 
-   deque_base(const allocator_type& a) 
+   explicit deque_base(const allocator_type& a) 
       :  members_(a)
    {}
 

From 3d8439595fd1af63763b4aa363a98776c5979c9d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= 
Date: Mon, 26 Dec 2011 11:09:52 +0000
Subject: [PATCH 13/14] Documentation fixes

[SVN r76169]
---
 doc/container.qbk | 17 +++++++++++++++--
 proj/to-do.txt    | 44 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/doc/container.qbk b/doc/container.qbk
index a9c4337..1fd0899 100644
--- a/doc/container.qbk
+++ b/doc/container.qbk
@@ -60,7 +60,7 @@ compiler include path.
 [*Boost.Container] requires a decent C++98 compatibility. Some compilers known to work are:
 
 *  Visual C++ >= 7.1.
-*  GCC >= 3.4.
+*  GCC >= 4.1.
 *  Intel C++ >= 9.0
 
 [endsect]
@@ -584,7 +584,20 @@ use [*Boost.Container]? There are several reasons for that:
 
 [section:release_notes Release Notes]
 
-*  First release with Boost 1.48. Container code from [*Boost.Interprocess] was deleted
+[section:release_notes_boost_1_49_00 Boost 1.49 Release]
+
+*  Fixed bugs
+  [@https://svn.boost.org/trac/boost/ticket/6205 #6205],
+  [@https://svn.boost.org/trac/boost/ticket/6287 #6287],
+  [@https://svn.boost.org/trac/boost/ticket/4383 #4383].
+
+[endsect]
+
+[section:release_notes_boost_1_48_00 Boost 1.48 Release]
+
+*  First release. Container code from [*Boost.Interprocess] was deleted
    and redirected to [*Boost.Container ] via using directives.
 
 [endsect]
+
+[endsect]
diff --git a/proj/to-do.txt b/proj/to-do.txt
index c7f77cf..d82bd8a 100644
--- a/proj/to-do.txt
+++ b/proj/to-do.txt
@@ -1,2 +1,46 @@
 ->Change "insert" and "push_back"/"push_front" to catch non-const rvalues
 ->Add an example with stateful allocators
+->Add test to check convertible types in push_back/insert
+
+
+Review allocator traits
+-> Explicit instantiation of simple allocator & std::allocator to detect missing allocator_traits calls
+-> Avoid any rebind<>::other
+-> Review select_on_container_copy_xxx
+-> Review propagate_on_xxx
+-> Put default constructed containers with their own constructor (different nothrow guarantees). Optimization, not needed
+-> Default + swap move constructors correct?
+-> Review container documentation in swap/copy/move regarding allocators
+
+Check all move constructors: swap might not be a valid idiom, allocators must be move constructed, intrusive containers are now movable
+
+Add and test:
+
+Test different propagation values and with inequal allocators
+
+
+propagate_on_container_move_assignment
+select_on_container_copy_construction
+propagate_on_container_swap
+propagate_on_container_copy_assignment
+
+Test move constructors with data values and unequal allocators
+
+An allocator should use a smart allocator not constructible from raw pointers to catch missing pointer_traits calls
+
+Review all internal container swap's to check allocator propagation is correct
+
+Add initializer lists
+
+Write forward_list
+
+Review all move constructors to test if allocator is move constructed
+
+check move if noexcept conditions in vector, deque and stable_vector
+
+Add new allocator propagation copy constructors
+
+Review all destructors (search for "~") to detect placement destruction and replace it with allocator_traits::destroy
+
+All functions from base classes like vector_base, node_alloc_holder, etc., should be named with underscore or
+similar to avoid namespace pollution.
\ No newline at end of file

From ba4a746a77237916417fe0fc5178c28f92d4ff4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= 
Date: Mon, 26 Dec 2011 16:37:49 +0000
Subject: [PATCH 14/14] Documentation update

[SVN r76177]
---
 doc/container.qbk | 40 ++++++++++++++++++++++------------------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/doc/container.qbk b/doc/container.qbk
index 1fd0899..54f37c3 100644
--- a/doc/container.qbk
+++ b/doc/container.qbk
@@ -412,7 +412,7 @@ a finite (10) number of parameters.
 
 [endsect]
 
-[section:alloc_traits_move_traits Stateful allocators and Scoped allocators]
+[section:alloc_traits_move_traits Stateful allocators]
 
 C++03 was not stateful-allocator friendly. For compactness of container objects and for
 simplicity, it did not require containers to support allocators with state: Allocator objects
@@ -422,24 +422,18 @@ to suppose two allocators of the same type always compare equal (that means that
 by one allocator object could be deallocated by another instance of the same type) and
 allocators were not swapped when the container was swapped.
 
-Many C++ container implementors felt C++03 guarantees were too weak and started to offer extensions.
-[*Boost.Container], following [@http://www.boost.org/libs/interprocess/ Boost.Interprocess] 
-containers experience supporting stateful allocators, offers the following guarantees:
-
-* Allocators are copy-constructed in copy/move constructors
-* If possible, a single allocator is hold to construct `value_type` and this allocator is copy constructed
-  from the user-supplied allocator object during container's constructor. If the container needs an auxiliary 
-  allocator (e.g. a array allocator used by `deque` or `stable_vector`), that allocator is also 
-  copy-constructed from the user-supplied allocator when the container is constructed (i.e. it's 
-  not constructed on the fly when auxiliary memory is needed).
-* Allocators are compared for equality when swapping containers. If allocators don't compare
-  equal allocators are swapped using an unqualified `swap` call.
-
 C++11 further improves stateful allocator support through the
 [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2554.pdf
-Scoped Allocators model], using classes like `std::scoped_allocator_adaptor` and `std::allocator_traits`.
-[*Boost.Container does not support it yet, but there are plans to do so and backport scoped allocator
-support to C++03 compilers.
+Scoped Allocators model]. [@http://en.cppreference.com/w/cpp/memory/allocator_traits
+`std::allocator_traits`] is the protocol between a container and an allocator, and
+an allocator writer can customize its behaviour (should the container propagate it in
+move constructor, swap, etc.?) following `allocator_traits` requirements. [*Boost.Container]
+not only supports this model with C++11 but also [*backports it to C++03]. 
+
+If possible, a single allocator is hold to construct `value_type`. If the container needs an auxiliary 
+allocator (e.g. a array allocator used by `deque` or `stable_vector`), that allocator is also 
+constructed from the user-supplied allocator when the container is constructed (i.e. it's 
+not constructed on the fly when auxiliary memory is needed).
 
 [endsect]
 
@@ -451,7 +445,14 @@ to C++03 compilers.
 
 [endsect]
 
-[section:Vector_bool vector]
+[section:forward_list `forward_list`]
+
+[*Boost.Container] does not offer C++11 `forward_list` container yet, but it will be available in future
+versions.
+
+[endsect]
+
+[section:Vector_bool `vector`]
 
 `vector` specialization has been quite problematic, and there have been several
 unsuccessful tries to deprecate or remove it from the standard. [*Boost.Container] does not implement it
@@ -591,6 +592,9 @@ use [*Boost.Container]? There are several reasons for that:
   [@https://svn.boost.org/trac/boost/ticket/6287 #6287],
   [@https://svn.boost.org/trac/boost/ticket/4383 #4383].
 
+*  Added `allocator_traits` support for both C++11 and C++03
+   compilers through an internal `allocator_traits` clone.
+
 [endsect]
 
 [section:release_notes_boost_1_48_00 Boost 1.48 Release]