diff --git a/include/boost/container/allocator_traits.hpp b/include/boost/container/allocator_traits.hpp index f1ce2fc..8e537cc 100644 --- a/include/boost/container/allocator_traits.hpp +++ b/include/boost/container/allocator_traits.hpp @@ -213,8 +213,8 @@ struct allocator_traits 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)...)` + //! Effects: calls `a.allocate(n, p)` if that call is well-formed; + //! otherwise, invokes `a.allocate(n)` static pointer allocate(Alloc &a, size_type n, const_void_pointer p) { const bool value = boost::container::container_detail:: diff --git a/include/boost/container/detail/destroyers.hpp b/include/boost/container/detail/destroyers.hpp index 3a42be3..d1b118c 100644 --- a/include/boost/container/detail/destroyers.hpp +++ b/include/boost/container/detail/destroyers.hpp @@ -65,6 +65,44 @@ struct null_scoped_array_deallocator {} }; +template +struct scoped_destroy_deallocator +{ + typedef boost::container::allocator_traits AllocTraits; + typedef typename AllocTraits::pointer pointer; + typedef typename AllocTraits::size_type size_type; + typedef container_detail::integral_constant::value> alloc_version; + typedef container_detail::integral_constant allocator_v1; + typedef container_detail::integral_constant allocator_v2; + + scoped_destroy_deallocator(pointer p, Allocator& a) + : m_ptr(p), m_alloc(a) {} + + ~scoped_destroy_deallocator() + { + if(m_ptr){ + AllocTraits::destroy(m_alloc, container_detail::to_raw_pointer(m_ptr)); + priv_deallocate(m_ptr, alloc_version()); + } + } + + void release() + { m_ptr = 0; } + + private: + + void priv_deallocate(const pointer &p, allocator_v1) + { AllocTraits::deallocate(m_alloc, p, 1); } + + void priv_deallocate(const pointer &p, allocator_v2) + { m_alloc.deallocate_one(p); } + + pointer m_ptr; + Allocator& m_alloc; +}; + //!A deleter for scoped_ptr that destroys //!an object using a STL allocator. @@ -150,6 +188,27 @@ class scoped_destructor A &a_; }; + +template +class value_destructor +{ + typedef boost::container::allocator_traits AllocTraits; + public: + typedef typename A::value_type value_type; + value_destructor(A &a, value_type &rv) + : rv_(rv), a_(a) + {} + + ~value_destructor() + { + AllocTraits::destroy(a_, &rv_); + } + + private: + value_type &rv_; + A &a_; +}; + template class allocator_destroyer { diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 739c844..23be0bf 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -395,14 +395,13 @@ class flat_tree 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); + value_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; } @@ -413,13 +412,12 @@ class flat_tree 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); + value_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; } @@ -430,10 +428,9 @@ class flat_tree 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); + value_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; } @@ -444,11 +441,10 @@ class flat_tree 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); + value_destructor d(a, val); insert_commit_data data; this->priv_insert_equal_prepare(hint, val, data); iterator i = priv_insert_commit(data, boost::move(val)); - d.release(); return i; } @@ -464,13 +460,12 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); \ stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - scoped_destructor d(a, &val); \ + value_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; \ } \ \ @@ -483,13 +478,12 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); \ stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - scoped_destructor d(a, &val); \ + value_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; \ } \ \ @@ -501,10 +495,9 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); \ stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - scoped_destructor d(a, &val); \ + value_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; \ } \ \ @@ -517,11 +510,10 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); \ stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - scoped_destructor d(a, &val); \ + value_destructor d(a, val); \ insert_commit_data data; \ this->priv_insert_equal_prepare(hint, val, data); \ iterator i = priv_insert_commit(data, boost::move(val)); \ - d.release(); \ return i; \ } \ diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 50212ce..3ab1536 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -745,12 +745,14 @@ class rbtree { value_type &v = p->get_data(); insert_commit_data data; + scoped_destroy_deallocator destroy_deallocator(p, this->node_alloc()); std::pair ret = this->insert_unique_check(KeyOfValue()(v), data); if(!ret.second){ - Destroyer(this->node_alloc())(p); return ret; } + //No throw insertion part, release rollback + destroy_deallocator.release(); return std::pair ( iterator(iiterator(this->icont().insert_unique_commit(*p, data))) , true ); diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 18a3c5e..0142500 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -264,21 +264,21 @@ class flat_map //! //! Complexity: Constant. key_compare key_comp() const - { return container_detail::force(m_flat_tree.key_comp()); } + { return container_detail::force_copy(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(container_detail::force(m_flat_tree.key_comp())); } + { return value_compare(container_detail::force_copy(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 container_detail::force(m_flat_tree.get_allocator()); } + { return container_detail::force_copy(m_flat_tree.get_allocator()); } const stored_allocator_type &get_stored_allocator() const { return container_detail::force(m_flat_tree.get_stored_allocator()); } @@ -300,7 +300,7 @@ class flat_map //! //! Complexity: Constant. const_iterator begin() const - { return container_detail::force(m_flat_tree.begin()); } + { return container_detail::force_copy(m_flat_tree.begin()); } //! Effects: Returns an iterator to the end of the container. //! @@ -316,7 +316,7 @@ class flat_map //! //! Complexity: Constant. const_iterator end() const - { return container_detail::force(m_flat_tree.end()); } + { return container_detail::force_copy(m_flat_tree.end()); } //! Effects: Returns a reverse_iterator pointing to the beginning //! of the reversed container. @@ -325,7 +325,7 @@ class flat_map //! //! Complexity: Constant. reverse_iterator rbegin() - { return container_detail::force(m_flat_tree.rbegin()); } + { return container_detail::force_copy(m_flat_tree.rbegin()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning //! of the reversed container. @@ -334,7 +334,7 @@ class flat_map //! //! Complexity: Constant. const_reverse_iterator rbegin() const - { return container_detail::force(m_flat_tree.rbegin()); } + { return container_detail::force_copy(m_flat_tree.rbegin()); } //! Effects: Returns a reverse_iterator pointing to the end //! of the reversed container. @@ -343,7 +343,7 @@ class flat_map //! //! Complexity: Constant. reverse_iterator rend() - { return container_detail::force(m_flat_tree.rend()); } + { return container_detail::force_copy(m_flat_tree.rend()); } //! Effects: Returns a const_reverse_iterator pointing to the end //! of the reversed container. @@ -352,7 +352,7 @@ class flat_map //! //! Complexity: Constant. const_reverse_iterator rend() const - { return container_detail::force(m_flat_tree.rend()); } + { return container_detail::force_copy(m_flat_tree.rend()); } //! Effects: Returns a const_iterator to the first element contained in the container. //! @@ -360,7 +360,7 @@ class flat_map //! //! Complexity: Constant. const_iterator cbegin() const - { return container_detail::force(m_flat_tree.cbegin()); } + { return container_detail::force_copy(m_flat_tree.cbegin()); } //! Effects: Returns a const_iterator to the end of the container. //! @@ -368,7 +368,7 @@ class flat_map //! //! Complexity: Constant. const_iterator cend() const - { return container_detail::force(m_flat_tree.cend()); } + { return container_detail::force_copy(m_flat_tree.cend()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning //! of the reversed container. @@ -377,7 +377,7 @@ class flat_map //! //! Complexity: Constant. const_reverse_iterator crbegin() const - { return container_detail::force(m_flat_tree.crbegin()); } + { return container_detail::force_copy(m_flat_tree.crbegin()); } //! Effects: Returns a const_reverse_iterator pointing to the end //! of the reversed container. @@ -386,7 +386,7 @@ class flat_map //! //! Complexity: Constant. const_reverse_iterator crend() const - { return container_detail::force(m_flat_tree.crend()); } + { return container_detail::force_copy(m_flat_tree.crend()); } //! Effects: Returns true if the container contains no elements. //! @@ -477,7 +477,7 @@ class flat_map //! //! Note: If an element is inserted it might invalidate elements. std::pair insert(const value_type& x) - { return container_detail::force >( + { return container_detail::force_copy >( m_flat_tree.insert_unique(container_detail::force(x))); } //! Effects: Inserts a new value_type move constructed from the pair if and @@ -492,7 +492,7 @@ class flat_map //! //! Note: If an element is inserted it might invalidate elements. std::pair insert(BOOST_RV_REF(value_type) x) - { return container_detail::force >( + { return container_detail::force_copy >( m_flat_tree.insert_unique(boost::move(container_detail::force(x)))); } //! Effects: Inserts a new value_type move constructed from the pair if and @@ -508,7 +508,7 @@ class flat_map //! Note: If an element is inserted it might invalidate elements. std::pair insert(BOOST_RV_REF(movable_value_type) x) { - return container_detail::force > + return container_detail::force_copy > (m_flat_tree.insert_unique(boost::move(x))); } @@ -524,8 +524,11 @@ class flat_map //! //! 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))); } + { + return container_detail::force_copy( + m_flat_tree.insert_unique( container_detail::force_copy(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. @@ -539,7 +542,7 @@ class flat_map 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) + (m_flat_tree.insert_unique( container_detail::force_copy(position) , boost::move(container_detail::force(x)))); } @@ -555,7 +558,7 @@ class flat_map iterator insert(const_iterator position, BOOST_RV_REF(movable_value_type) x) { return container_detail::force_copy( - m_flat_tree.insert_unique(container_detail::force(position), boost::move(x))); + m_flat_tree.insert_unique(container_detail::force_copy(position), boost::move(x))); } //! Requires: first, last are not iterators into *this. @@ -620,8 +623,11 @@ class flat_map //! 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)...)); } + { + return container_detail::force_copy + (m_flat_tree.emplace_hint_unique( container_detail::force_copy(hint) + , boost::forward(args)...)); + } #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING @@ -635,7 +641,7 @@ class flat_map 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) \ + (container_detail::force_copy(hint) \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \ //! #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) @@ -654,7 +660,10 @@ class flat_map //! Note: Invalidates elements with keys //! not less than the erased element. iterator erase(const_iterator position) - { return container_detail::force_copy(m_flat_tree.erase(container_detail::force(position))); } + { + return container_detail::force_copy + (m_flat_tree.erase(container_detail::force_copy(position))); + } //! Effects: Erases all elements in the container with key equivalent to x. //! @@ -674,8 +683,11 @@ 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 container_detail::force_copy - (m_flat_tree.erase(container_detail::force(first), container_detail::force(last))); } + { + return container_detail::force_copy( + m_flat_tree.erase( container_detail::force_copy(first) + , container_detail::force_copy(last))); + } //! Effects: erase(a.begin(),a.end()). //! @@ -706,7 +718,7 @@ class flat_map //! //! Complexity: Logarithmic.s const_iterator find(const key_type& x) const - { return container_detail::force(m_flat_tree.find(x)); } + { return container_detail::force_copy(m_flat_tree.find(x)); } //! Returns: The number of elements with key equivalent to x. //! @@ -726,7 +738,7 @@ class flat_map //! //! Complexity: Logarithmic const_iterator lower_bound(const key_type& x) const - { return container_detail::force(m_flat_tree.lower_bound(x)); } + { return container_detail::force_copy(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. @@ -740,7 +752,7 @@ class flat_map //! //! Complexity: Logarithmic const_iterator upper_bound(const key_type& x) const - { return container_detail::force(m_flat_tree.upper_bound(x)); } + { return container_detail::force_copy(m_flat_tree.upper_bound(x)); } //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! @@ -1050,21 +1062,21 @@ class flat_multimap //! //! Complexity: Constant. key_compare key_comp() const - { return container_detail::force(m_flat_tree.key_comp()); } + { return container_detail::force_copy(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(container_detail::force(m_flat_tree.key_comp())); } + { return value_compare(container_detail::force_copy(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 container_detail::force(m_flat_tree.get_allocator()); } + { return container_detail::force_copy(m_flat_tree.get_allocator()); } const stored_allocator_type &get_stored_allocator() const { return container_detail::force(m_flat_tree.get_stored_allocator()); } @@ -1086,7 +1098,7 @@ class flat_multimap //! //! Complexity: Constant. const_iterator begin() const - { return container_detail::force(m_flat_tree.begin()); } + { return container_detail::force_copy(m_flat_tree.begin()); } //! Effects: Returns an iterator to the end of the container. //! @@ -1102,7 +1114,7 @@ class flat_multimap //! //! Complexity: Constant. const_iterator end() const - { return container_detail::force(m_flat_tree.end()); } + { return container_detail::force_copy(m_flat_tree.end()); } //! Effects: Returns a reverse_iterator pointing to the beginning //! of the reversed container. @@ -1111,7 +1123,7 @@ class flat_multimap //! //! Complexity: Constant. reverse_iterator rbegin() - { return container_detail::force(m_flat_tree.rbegin()); } + { return container_detail::force_copy(m_flat_tree.rbegin()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning //! of the reversed container. @@ -1120,7 +1132,7 @@ class flat_multimap //! //! Complexity: Constant. const_reverse_iterator rbegin() const - { return container_detail::force(m_flat_tree.rbegin()); } + { return container_detail::force_copy(m_flat_tree.rbegin()); } //! Effects: Returns a reverse_iterator pointing to the end //! of the reversed container. @@ -1129,7 +1141,7 @@ class flat_multimap //! //! Complexity: Constant. reverse_iterator rend() - { return container_detail::force(m_flat_tree.rend()); } + { return container_detail::force_copy(m_flat_tree.rend()); } //! Effects: Returns a const_reverse_iterator pointing to the end //! of the reversed container. @@ -1138,7 +1150,7 @@ class flat_multimap //! //! Complexity: Constant. const_reverse_iterator rend() const - { return container_detail::force(m_flat_tree.rend()); } + { return container_detail::force_copy(m_flat_tree.rend()); } //! Effects: Returns a const_iterator to the first element contained in the container. //! @@ -1146,7 +1158,7 @@ class flat_multimap //! //! Complexity: Constant. const_iterator cbegin() const - { return container_detail::force(m_flat_tree.cbegin()); } + { return container_detail::force_copy(m_flat_tree.cbegin()); } //! Effects: Returns a const_iterator to the end of the container. //! @@ -1154,7 +1166,7 @@ class flat_multimap //! //! Complexity: Constant. const_iterator cend() const - { return container_detail::force(m_flat_tree.cend()); } + { return container_detail::force_copy(m_flat_tree.cend()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning //! of the reversed container. @@ -1163,7 +1175,7 @@ class flat_multimap //! //! Complexity: Constant. const_reverse_iterator crbegin() const - { return container_detail::force(m_flat_tree.crbegin()); } + { return container_detail::force_copy(m_flat_tree.crbegin()); } //! Effects: Returns a const_reverse_iterator pointing to the end //! of the reversed container. @@ -1172,7 +1184,7 @@ class flat_multimap //! //! Complexity: Constant. const_reverse_iterator crend() const - { return container_detail::force(m_flat_tree.crend()); } + { return container_detail::force_copy(m_flat_tree.crend()); } //! Effects: Returns true if the container contains no elements. //! @@ -1214,7 +1226,10 @@ class flat_multimap //! //! 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))); } + { + 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. @@ -1248,8 +1263,11 @@ class flat_multimap //! //! 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))); } + { + return container_detail::force_copy + (m_flat_tree.insert_equal( container_detail::force_copy(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. @@ -1265,7 +1283,7 @@ class flat_multimap iterator insert(const_iterator position, BOOST_RV_REF(value_type) x) { return container_detail::force_copy - (m_flat_tree.insert_equal(container_detail::force(position) + (m_flat_tree.insert_equal(container_detail::force_copy(position) , boost::move(x))); } @@ -1283,7 +1301,7 @@ class flat_multimap iterator insert(const_iterator position, BOOST_RV_REF(impl_value_type) x) { return container_detail::force_copy( - m_flat_tree.insert_equal(container_detail::force(position), boost::move(x))); + m_flat_tree.insert_equal(container_detail::force_copy(position), boost::move(x))); } //! Requires: first, last are not iterators into *this. @@ -1344,7 +1362,7 @@ class flat_multimap iterator emplace_hint(const_iterator hint, Args&&... args) { return container_detail::force_copy(m_flat_tree.emplace_hint_equal - (container_detail::force(hint), boost::forward(args)...)); + (container_detail::force_copy(hint), boost::forward(args)...)); } #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING @@ -1359,7 +1377,7 @@ class flat_multimap 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) \ + (container_detail::force_copy(hint) \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \ //! #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) @@ -1378,7 +1396,10 @@ class flat_multimap //! Note: Invalidates elements with keys //! not less than the erased element. iterator erase(const_iterator position) - { return container_detail::force_copy(m_flat_tree.erase(container_detail::force(position))); } + { + return container_detail::force_copy( + m_flat_tree.erase(container_detail::force_copy(position))); + } //! Effects: Erases all elements in the container with key equivalent to x. //! @@ -1398,8 +1419,11 @@ 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 container_detail::force_copy - (m_flat_tree.erase(container_detail::force(first), container_detail::force(last))); } + { + return container_detail::force_copy + (m_flat_tree.erase( container_detail::force_copy(first) + , container_detail::force_copy(last))); + } //! Effects: erase(a.begin(),a.end()). //! @@ -1430,7 +1454,7 @@ class flat_multimap //! //! Complexity: Logarithmic. const_iterator find(const key_type& x) const - { return container_detail::force(m_flat_tree.find(x)); } + { return container_detail::force_copy(m_flat_tree.find(x)); } //! Returns: The number of elements with key equivalent to x. //! @@ -1450,7 +1474,7 @@ class flat_multimap //! //! Complexity: Logarithmic const_iterator lower_bound(const key_type& x) const - { return container_detail::force(m_flat_tree.lower_bound(x)); } + { return container_detail::force_copy(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. @@ -1464,20 +1488,20 @@ class flat_multimap //! //! Complexity: Logarithmic const_iterator upper_bound(const key_type& x) const - { return container_detail::force(m_flat_tree.upper_bound(x)); } + { return container_detail::force_copy(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 container_detail::force >(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 container_detail::force >(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(). diff --git a/include/boost/container/scoped_allocator.hpp b/include/boost/container/scoped_allocator.hpp index d7115d8..7da71bd 100644 --- a/include/boost/container/scoped_allocator.hpp +++ b/include/boost/container/scoped_allocator.hpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -31,50 +32,9 @@ #include #include -#if defined(BOOST_NO_VARIADIC_TEMPLATES) -#include -#endif namespace boost { namespace container { -#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) - -#if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) - -template -class scoped_allocator_adaptor; - -#else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) - -template -class scoped_allocator_adaptor; - -template -class scoped_allocator_adaptor; - -#endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) - - -#else // #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - -template -class scoped_allocator_adaptor; - -#endif - -//! The allocator_arg_t struct is an empty structure type used as a unique type to -//! disambiguate constructor and function overloading. Specifically, several types -//! have constructors with allocator_arg_t as the first argument, immediately followed -//! by an argument of a type that satisfies the Allocator requirements -struct allocator_arg_t{}; - -//! A instance of type allocator_arg_t -//! -static const allocator_arg_t allocator_arg = allocator_arg_t(); - //! Remark: if a specialization is derived from true_type, indicates that T may be constructed //! with an allocator as its last constructor argument. Ideally, all constructors of T (including the //! copy and move constructors) should have a variant that accepts a final argument of diff --git a/include/boost/container/scoped_allocator_fwd.hpp b/include/boost/container/scoped_allocator_fwd.hpp new file mode 100644 index 0000000..0814a50 --- /dev/null +++ b/include/boost/container/scoped_allocator_fwd.hpp @@ -0,0 +1,83 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP +#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP + +#if (defined MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#if defined(BOOST_NO_VARIADIC_TEMPLATES) +#include +#include +#endif + +namespace boost { namespace container { + +///@cond + +#if !defined(BOOST_NO_VARIADIC_TEMPLATES) + + #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) + + template + class scoped_allocator_adaptor; + + #else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) + + template + class scoped_allocator_adaptor; + + template + class scoped_allocator_adaptor; + + #endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) + + +#else // #if !defined(BOOST_NO_VARIADIC_TEMPLATES) + +template +class scoped_allocator_adaptor; + +#endif + +///@endcond + +//! The allocator_arg_t struct is an empty structure type used as a unique type to +//! disambiguate constructor and function overloading. Specifically, several types +//! have constructors with allocator_arg_t as the first argument, immediately followed +//! by an argument of a type that satisfies the Allocator requirements +struct allocator_arg_t{}; + +//! A instance of type allocator_arg_t +//! +static const allocator_arg_t allocator_arg = allocator_arg_t(); + +template +struct constructible_with_allocator_suffix; + +template +struct constructible_with_allocator_prefix; + +template +struct uses_allocator; + +}} // namespace boost { namespace container { + +#include + +#endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index dc2fdd9..2a64cec 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include