diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 960a491..81c1802 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -32,6 +32,8 @@ #include #include #include +#include +#include namespace boost { @@ -173,6 +175,10 @@ class flat_tree //!Standard extension typedef allocator_type stored_allocator_type; + private: + typedef allocator_traits stored_allocator_traits; + + public: flat_tree() : m_data() { } @@ -377,44 +383,65 @@ class flat_tree template std::pair emplace_unique(Args&&... args) { - value_type && val = value_type(boost::forward(args)...); + aligned_storage::value> v; + value_type &val = *static_cast(static_cast(&v)); + stored_allocator_type &a = this->get_stored_allocator(); + stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); + scoped_destructor d(a, &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)); } + d.release(); return ret; } template iterator emplace_hint_unique(const_iterator hint, Args&&... args) { - value_type && val = value_type(boost::forward(args)...); + aligned_storage::value> v; + value_type &val = *static_cast(static_cast(&v)); + stored_allocator_type &a = this->get_stored_allocator(); + stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); + scoped_destructor d(a, &val); 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)); } + d.release(); return ret.first; } template iterator emplace_equal(Args&&... args) { - value_type &&val = value_type(boost::forward(args)...); + aligned_storage::value> v; + value_type &val = *static_cast(static_cast(&v)); + stored_allocator_type &a = this->get_stored_allocator(); + stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); + scoped_destructor d(a, &val); iterator i = this->upper_bound(KeyOfValue()(val)); i = this->m_data.m_vect.insert(i, boost::move(val)); + d.release(); return i; } template iterator emplace_hint_equal(const_iterator hint, Args&&... args) { - value_type &&val = value_type(boost::forward(args)...); + aligned_storage::value> v; + value_type &val = *static_cast(static_cast(&v)); + stored_allocator_type &a = this->get_stored_allocator(); + stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); + scoped_destructor d(a, &val); insert_commit_data data; this->priv_insert_equal_prepare(hint, val, data); - return priv_insert_commit(data, boost::move(val)); + iterator i = priv_insert_commit(data, boost::move(val)); + d.release(); + return i; } #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING @@ -424,15 +451,18 @@ class flat_tree std::pair \ emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ { \ - 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; \ + aligned_storage::value> v; \ + value_type &val = *static_cast(static_cast(&v)); \ + stored_allocator_type &a = this->get_stored_allocator(); \ + stored_allocator_traits::construct(a, &val \ + BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ + scoped_destructor d(a, &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)); \ } \ + d.release(); \ return ret; \ } \ \ @@ -440,27 +470,33 @@ class flat_tree iterator emplace_hint_unique(const_iterator hint \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ { \ - 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; \ + aligned_storage::value> v; \ + value_type &val = *static_cast(static_cast(&v)); \ + stored_allocator_type &a = this->get_stored_allocator(); \ + stored_allocator_traits::construct(a, &val \ + BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ + scoped_destructor d(a, &val); \ 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)); \ } \ + d.release(); \ return ret.first; \ } \ \ 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, _)) \ { \ - 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; \ + aligned_storage::value> v; \ + value_type &val = *static_cast(static_cast(&v)); \ + stored_allocator_type &a = this->get_stored_allocator(); \ + stored_allocator_traits::construct(a, &val \ + BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ + scoped_destructor d(a, &val); \ iterator i = this->upper_bound(KeyOfValue()(val)); \ i = this->m_data.m_vect.insert(i, boost::move(val)); \ + d.release(); \ return i; \ } \ \ @@ -468,14 +504,19 @@ class flat_tree iterator emplace_hint_equal(const_iterator hint \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ { \ - 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; \ + aligned_storage::value> v; \ + value_type &val = *static_cast(static_cast(&v)); \ + stored_allocator_type &a = this->get_stored_allocator(); \ + stored_allocator_traits::construct(a, &val \ + BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ + scoped_destructor d(a, &val); \ insert_commit_data data; \ this->priv_insert_equal_prepare(hint, val, data); \ - return priv_insert_commit(data, boost::move(val)); \ + iterator i = priv_insert_commit(data, boost::move(val)); \ + d.release(); \ + return i; \ } \ + //! #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index f2b8e34..28ef1d6 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -300,14 +300,6 @@ class flat_map const_iterator begin() const { return container_detail::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 container_detail::force(m_flat_tree.cbegin()); } - //! Effects: Returns an iterator to the end of the container. //! //! Throws: Nothing. @@ -324,14 +316,6 @@ class flat_map const_iterator end() const { return container_detail::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 container_detail::force(m_flat_tree.cend()); } - //! Effects: Returns a reverse_iterator pointing to the beginning //! of the reversed container. //! @@ -350,15 +334,6 @@ class flat_map const_reverse_iterator rbegin() const { return container_detail::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 container_detail::force(m_flat_tree.crbegin()); } - //! Effects: Returns a reverse_iterator pointing to the end //! of the reversed container. //! @@ -377,6 +352,31 @@ class flat_map const_reverse_iterator rend() const { return container_detail::force(m_flat_tree.rend()); } + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return container_detail::force(m_flat_tree.cbegin()); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return container_detail::force(m_flat_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 container_detail::force(m_flat_tree.crbegin()); } + //! Effects: Returns a const_reverse_iterator pointing to the end //! of the reversed container. //! @@ -1119,6 +1119,40 @@ class flat_multimap const_reverse_iterator rend() const { return container_detail::force(m_flat_tree.rend()); } + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return container_detail::force(m_flat_tree.cbegin()); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return container_detail::force(m_flat_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 container_detail::force(m_flat_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 container_detail::force(m_flat_tree.crend()); } + //! Effects: Returns true if the container contains no elements. //! //! Throws: Nothing. diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 744ddff..e6682d8 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -65,6 +65,10 @@ template struct list_node : public list_hook::type { + private: + list_node(); + + public: typedef typename list_hook::type hook_type; T m_data; }; diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index 25403e0..b22e794 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -276,6 +276,14 @@ class map //! //! Complexity: Constant. const_iterator begin() const + { return this->cbegin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const { return m_tree.begin(); } //! Effects: Returns an iterator to the end of the container. @@ -292,6 +300,14 @@ class map //! //! Complexity: Constant. const_iterator end() const + { return this->cend(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const { return m_tree.end(); } //! Effects: Returns a reverse_iterator pointing to the beginning @@ -310,6 +326,15 @@ class map //! //! Complexity: Constant. const_reverse_iterator rbegin() const + { return this->crbegin(); } + + //! 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.rbegin(); } //! Effects: Returns a reverse_iterator pointing to the end @@ -328,6 +353,15 @@ class map //! //! Complexity: Constant. const_reverse_iterator rend() const + { return this->crend(); } + + //! 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.rend(); } //! Effects: Returns true if the container contains no elements. @@ -984,6 +1018,14 @@ class multimap //! //! Complexity: Constant. const_iterator begin() const + { return this->cbegin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const { return m_tree.begin(); } //! Effects: Returns an iterator to the end of the container. @@ -1000,6 +1042,14 @@ class multimap //! //! Complexity: Constant. const_iterator end() const + { return this->cend(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const { return m_tree.end(); } //! Effects: Returns a reverse_iterator pointing to the beginning @@ -1018,6 +1068,15 @@ class multimap //! //! Complexity: Constant. const_reverse_iterator rbegin() const + { return this->crbegin(); } + + //! 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.rbegin(); } //! Effects: Returns a reverse_iterator pointing to the end @@ -1036,6 +1095,15 @@ class multimap //! //! Complexity: Constant. const_reverse_iterator rend() const + { return this->crend(); } + + //! 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.rend(); } //! Effects: Returns true if the container contains no elements. diff --git a/include/boost/container/scoped_allocator.hpp b/include/boost/container/scoped_allocator.hpp index d9023f8..770158a 100644 --- a/include/boost/container/scoped_allocator.hpp +++ b/include/boost/container/scoped_allocator.hpp @@ -674,6 +674,20 @@ class scoped_allocator_adaptor_base , inner(other.inner_allocator()) {} + protected: + struct internal_type_t{}; + + template + scoped_allocator_adaptor_base + ( internal_type_t + , BOOST_FWD_REF(OuterA2) outerAlloc + , const inner_allocator_type &inner) + : outer_allocator_type(::boost::forward(outerAlloc)) + , m_inner(inner) + {} + + public: + scoped_allocator_adaptor_base &operator= (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other) { @@ -772,17 +786,17 @@ class scoped_allocator_adaptor_base(outerAlloc)) \ - , inner(BOOST_PP_ENUM_PARAMS(n, q)) \ + , m_inner(BOOST_PP_ENUM_PARAMS(n, q)) \ {} \ \ scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other) \ : outer_allocator_type(other.outer_allocator()) \ - , inner(other.inner_allocator()) \ + , m_inner(other.inner_allocator()) \ {} \ \ scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other) \ : outer_allocator_type(::boost::move(other.outer_allocator())) \ - , inner(::boost::move(other.inner_allocator())) \ + , m_inner(::boost::move(other.inner_allocator())) \ {} \ \ template \ @@ -793,7 +807,7 @@ class scoped_allocator_adaptor_base& other) \ : outer_allocator_type(other.outer_allocator()) \ - , inner(other.inner_allocator()) \ + , m_inner(other.inner_allocator()) \ {} \ \ template \ @@ -805,29 +819,42 @@ class scoped_allocator_adaptor_base BOOST_RV_REF_END other) \ : outer_allocator_type(other.outer_allocator()) \ - , inner(other.inner_allocator()) \ + , m_inner(other.inner_allocator()) \ {} \ \ + protected: \ + struct internal_type_t{}; \ + \ + template \ + scoped_allocator_adaptor_base \ + ( internal_type_t \ + , BOOST_FWD_REF(OuterA2) outerAlloc \ + , const inner_allocator_type &inner) \ + : outer_allocator_type(::boost::forward(outerAlloc)) \ + , m_inner(inner) \ + {} \ + \ + public: \ scoped_allocator_adaptor_base &operator= \ (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other) \ { \ outer_allocator_type::operator=(other.outer_allocator()); \ - inner = other.inner_allocator(); \ + m_inner = other.inner_allocator(); \ return *this; \ } \ \ scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other) \ { \ outer_allocator_type::operator=(boost::move(other.outer_allocator())); \ - inner = ::boost::move(other.inner_allocator()); \ + m_inner = ::boost::move(other.inner_allocator()); \ return *this; \ } \ \ inner_allocator_type& inner_allocator() \ - { return inner; } \ + { return m_inner; } \ \ inner_allocator_type const& inner_allocator() const \ - { return inner; } \ + { return m_inner; } \ \ outer_allocator_type & outer_allocator() \ { return static_cast(*this); } \ @@ -836,7 +863,7 @@ class scoped_allocator_adaptor_base(*this); } \ \ private: \ - inner_allocator_type inner; \ + inner_allocator_type m_inner; \ }; \ //! #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) @@ -920,6 +947,15 @@ class scoped_allocator_adaptor_base : outer_allocator_type(other.outer_allocator()) {} + protected: + struct internal_type_t{}; + + template + scoped_allocator_adaptor_base(internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &) + : outer_allocator_type(::boost::forward(outerAlloc)) + {} + + public: scoped_allocator_adaptor_base &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other) { outer_allocator_type::operator=(other.outer_allocator()); @@ -1221,8 +1257,9 @@ class scoped_allocator_adaptor scoped_allocator_adaptor select_on_container_copy_construction() const { return scoped_allocator_adaptor - (outer_traits_type::select_on_container_copy_construction(this->outer_allocator()), - outer_traits_type::select_on_container_copy_construction(this->inner_allocator()) + (internal_type_t() + ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator()) + ,outer_traits_type::select_on_container_copy_construction(this->inner_allocator()) ); } /// @cond @@ -1309,11 +1346,11 @@ class scoped_allocator_adaptor template void construct(std::pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y) - { this->construct_pair(p, ::boost::forward(x), ::boost::forward(y)); } + { this->construct_pair(p, ::boost::forward(x), ::boost::forward(y)); } template void construct(container_detail::pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y) - { this->construct_pair(p, ::boost::forward(x), ::boost::forward(y)); } + { this->construct_pair(p, ::boost::forward(x), ::boost::forward(y)); } template void construct(std::pair* p, const std::pair& x) @@ -1391,6 +1428,12 @@ class scoped_allocator_adaptor //template //void construct(pair* p, piecewise_construct_t, tuple x, tuple y); + private: + template + scoped_allocator_adaptor(internal_type_t, BOOST_FWD_REF(OuterA2) outer, const inner_allocator_type& inner) + : base_type(internal_type_t(), ::boost::forward(outer), inner) + {} + /// @endcond }; diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index 70a2cbb..5797d6c 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -65,6 +65,10 @@ template struct slist_node : public slist_hook::type { + private: + slist_node(); + + public: typedef typename slist_hook::type hook_type; T m_data; }; diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 3f29a86..c6ca778 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -119,6 +119,10 @@ template struct node_type : public node_type_base { + private: + node_type(); + + public: T value; }; diff --git a/test/scoped_allocator_usage_test.cpp b/test/scoped_allocator_usage_test.cpp index e7af116..1fbd2ce 100644 --- a/test/scoped_allocator_usage_test.cpp +++ b/test/scoped_allocator_usage_test.cpp @@ -1,8 +1,18 @@ +#include #include -#include #include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include + #include template @@ -14,82 +24,372 @@ public: typedef typename std::allocator::size_type size_type; SimpleAllocator(int value) - : _value(value) + : m_state(value) {} template SimpleAllocator(const SimpleAllocator &other) - : _value(other._value) + : m_state(other.m_state) {} pointer allocate(size_type n) { - return _allocator.allocate(n); + return m_allocator.allocate(n); } + void deallocate(pointer p, size_type n) { - _allocator.deallocate(p, n); + m_allocator.deallocate(p, n); } -private: - int _value; - std::allocator _allocator; + + int get_value() const + { return m_state; } + + private: + int m_state; + std::allocator m_allocator; template friend class SimpleAllocator; }; -template -class ScopedAllocator : public boost::container::scoped_allocator_adaptor > +class alloc_int { -private: - typedef boost::container::scoped_allocator_adaptor > Base; + private: // Not copyable -public: - ScopedAllocator(int value) - : Base(SimpleAllocator(value)) - {} -}; + BOOST_MOVABLE_BUT_NOT_COPYABLE(alloc_int) -class Resource -{ -private: // Not copyable - Resource(const Resource &); - Resource &operator=(const Resource &); -public: + public: typedef SimpleAllocator allocator_type; - Resource(BOOST_RV_REF(Resource)other) - : _value(other._value), _allocator(boost::move(other._allocator)) + alloc_int(BOOST_RV_REF(alloc_int)other) + : m_value(other.m_value), m_allocator(boost::move(other.m_allocator)) { - other._value = -1; + other.m_value = -1; } - Resource(BOOST_RV_REF(Resource)other, const allocator_type &allocator) - : _value(other._value), _allocator(allocator) + alloc_int(BOOST_RV_REF(alloc_int)other, const allocator_type &allocator) + : m_value(other.m_value), m_allocator(allocator) { - other._value = -1; + other.m_value = -1; } - Resource(int value, const allocator_type &allocator) - : _value(value), _allocator(allocator) + alloc_int(int value, const allocator_type &allocator) + : m_value(value), m_allocator(allocator) {} -private: - int _value; - allocator_type _allocator; + + alloc_int & operator=(BOOST_RV_REF(alloc_int)other) + { + other.m_value = other.m_value; + return *this; + } + + int get_allocator_state() const + { return m_allocator.get_value(); } + + int get_value() const + { return m_value; } + + friend bool operator < (const alloc_int &l, const alloc_int &r) + { return l.m_value < r.m_value; } + + friend bool operator == (const alloc_int &l, const alloc_int &r) + { return l.m_value == r.m_value; } + + private: + int m_value; + allocator_type m_allocator; }; -typedef std::pair MapNode; +using namespace ::boost::container; -typedef boost::container::scoped_allocator_adaptor > MapAllocator; +//general allocator +typedef scoped_allocator_adaptor > AllocIntAllocator; -typedef boost::container::map, MapAllocator> Map; +//[multi]map/set +typedef std::pair MapNode; +typedef scoped_allocator_adaptor > MapAllocator; +typedef map, MapAllocator> Map; +typedef set, AllocIntAllocator> Set; +typedef multimap, MapAllocator> MultiMap; +typedef multiset, AllocIntAllocator> MultiSet; + +//[multi]flat_map/set +typedef std::pair FlatMapNode; +typedef scoped_allocator_adaptor > FlatMapAllocator; +typedef flat_map, MapAllocator> FlatMap; +typedef flat_set, AllocIntAllocator> FlatSet; +typedef flat_multimap, MapAllocator> FlatMultiMap; +typedef flat_multiset, AllocIntAllocator> FlatMultiSet; + +//vector, deque, list, slist, stable_vector. +typedef vector Vector; +typedef deque Deque; +typedef list List; +typedef slist Slist; +typedef stable_vector StableVector; + +///////// +//is_unique_assoc +///////// + +template +struct is_unique_assoc +{ + static const bool value = false; +}; + +template +struct is_unique_assoc< map > +{ + static const bool value = true; +}; + +template +struct is_unique_assoc< flat_map > +{ + static const bool value = true; +}; + +template +struct is_unique_assoc< set > +{ + static const bool value = true; +}; + +template +struct is_unique_assoc< flat_set > +{ + static const bool value = true; +}; + + +///////// +//is_map +///////// + +template +struct is_map +{ + static const bool value = false; +}; + +template +struct is_map< map > +{ + static const bool value = true; +}; + +template +struct is_map< flat_map > +{ + static const bool value = true; +}; + +template +struct is_map< multimap > +{ + static const bool value = true; +}; + +template +struct is_map< flat_multimap > +{ + static const bool value = true; +}; + +template +struct is_set +{ + static const bool value = false; +}; + +template +struct is_set< set > +{ + static const bool value = true; +}; + +template +struct is_set< flat_set > +{ + static const bool value = true; +}; + +template +struct is_set< multiset > +{ + static const bool value = true; +}; + +template +struct is_set< flat_multiset > +{ + static const bool value = true; +}; + +///////// +//container_wrapper +///////// + +template< class Container + , bool Assoc = is_set::value || is_map::value + , bool UniqueAssoc = is_unique_assoc::value + , bool Map = is_map::value + > +struct container_wrapper + : public Container +{ + typedef typename Container::allocator_type allocator_type; + + container_wrapper(const allocator_type &a) + : Container(a) + {} +}; + +template //map +struct container_wrapper + : public Container +{ + typedef typename Container::allocator_type allocator_type; + typedef typename Container::key_compare key_compare; + typedef typename Container::value_type value_type; + typedef typename Container::const_iterator const_iterator; + typedef typename Container::iterator iterator; + + container_wrapper(const allocator_type &a) + : Container(key_compare(), a) + {} + + template + iterator emplace(const_iterator, const Arg &arg) + { + return this->Container::emplace(arg, arg).first; + } +}; + +template //set +struct container_wrapper + : public Container +{ + typedef typename Container::allocator_type allocator_type; + typedef typename Container::key_compare key_compare; + typedef typename Container::value_type value_type; + typedef typename Container::const_iterator const_iterator; + typedef typename Container::iterator iterator; + + container_wrapper(const allocator_type &a) + : Container(key_compare(), a) + {} + + template + iterator emplace(const_iterator, const Arg &arg) + { + return this->Container::emplace(arg).first; + } +}; + +template //multimap +struct container_wrapper + : public Container +{ + typedef typename Container::value_type value_type; + typedef typename Container::key_compare key_compare; + typedef typename Container::allocator_type allocator_type; + typedef typename Container::const_iterator const_iterator; + typedef typename Container::iterator iterator; + + container_wrapper(const allocator_type &a) + : Container(key_compare(), a) + {} + + template + iterator emplace(const_iterator, const Arg &arg) + { + return this->Container::emplace(arg, arg); + } +}; + +//multiset +template //multimap +struct container_wrapper + : public Container +{ + typedef typename Container::value_type value_type; + typedef typename Container::key_compare key_compare; + typedef typename Container::allocator_type allocator_type; + typedef typename Container::const_iterator const_iterator; + typedef typename Container::iterator iterator; + + container_wrapper(const allocator_type &a) + : Container(key_compare(), a) + {} + + template + iterator emplace(const_iterator, const Arg &arg) + { + return this->Container::emplace(arg); + } +}; + +bool test_value_and_state_equals(const alloc_int &r, int value, int state) +{ return r.get_value() == value && r.get_allocator_state() == state; } + +template +bool test_value_and_state_equals(const container_detail::pair &p, int value, int state) +{ return test_value_and_state_equals(p.first, value, state) && test_alloc_state_equals(p.second, value, state); } + +template +bool test_value_and_state_equals(const std::pair &p, int value, int state) +{ return test_value_and_state_equals(p.first, value, state) && test_value_and_state_equals(p.second, value, state); } + +template +bool one_level_allocator_propagation_test() +{ + typedef container_wrapper ContainerWrapper; + typedef typename ContainerWrapper::iterator iterator; + ContainerWrapper c(SimpleAllocator(5)); + + c.clear(); + iterator it = c.emplace(c.cbegin(), 42); + + if(!test_value_and_state_equals(*it, 42, 5)) + return false; + + return true; +} int main() { - Map map1(std::less(), SimpleAllocator(5)); - - map1.emplace("foo", 42); - map1.emplace("bar", 11); - - //Map map2 = map1; + //unique assoc + if(!one_level_allocator_propagation_test()) + return 1; + if(!one_level_allocator_propagation_test()) + return 1; + if(!one_level_allocator_propagation_test()) + return 1; + if(!one_level_allocator_propagation_test()) + return 1; + //multi assoc + if(!one_level_allocator_propagation_test()) + return 1; + if(!one_level_allocator_propagation_test()) + return 1; + if(!one_level_allocator_propagation_test()) + return 1; + if(!one_level_allocator_propagation_test()) + return 1; + //sequence containers + if(!one_level_allocator_propagation_test()) + return 1; + if(!one_level_allocator_propagation_test()) + return 1; + if(!one_level_allocator_propagation_test()) + return 1; + if(!one_level_allocator_propagation_test()) + return 1; + if(!one_level_allocator_propagation_test()) + return 1; return 0; } + +#include