From 8ef4b5e1e435d6d409bc696e603529ee0e1a03e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 18 May 2013 21:04:54 +0000 Subject: [PATCH 01/26] Fixes #8553 [SVN r84359] --- doc/container.qbk | 4 +- include/boost/container/scoped_allocator.hpp | 29 +++++++++++ include/boost/container/static_vector.hpp | 53 +++++++++----------- test/scoped_allocator_adaptor_test.cpp | 14 ++++++ 4 files changed, 71 insertions(+), 29 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index daec5ce..2c3dd4e 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -666,7 +666,9 @@ use [*Boost.Container]? There are several reasons for that: * Fixed bugs [@https://svn.boost.org/trac/boost/ticket/7921 #7921], [@https://svn.boost.org/trac/boost/ticket/7969 #7969], [@https://svn.boost.org/trac/boost/ticket/8118 #8118], - [@https://svn.boost.org/trac/boost/ticket/8294 #8294]. + [@https://svn.boost.org/trac/boost/ticket/8294 #8294], + [@https://svn.boost.org/trac/boost/ticket/8553 #8553]. +* Added experimental `static_vector` class. [endsect] diff --git a/include/boost/container/scoped_allocator.hpp b/include/boost/container/scoped_allocator.hpp index 022c73e..f9f2108 100644 --- a/include/boost/container/scoped_allocator.hpp +++ b/include/boost/container/scoped_allocator.hpp @@ -664,6 +664,12 @@ class scoped_allocator_adaptor_base return *this; } + void swap(scoped_allocator_adaptor_base &r) + { + boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator()); + boost::container::swap_dispatch(this->m_inner, r.inner_allocator()); + } + inner_allocator_type& inner_allocator() { return m_inner; } @@ -812,6 +818,12 @@ class scoped_allocator_adaptor_baseouter_allocator(), r.outer_allocator()); \ + boost::container::swap_dispatch(this->m_inner, r.inner_allocator()); \ + } \ + \ inner_allocator_type& inner_allocator() \ { return m_inner; } \ \ @@ -931,6 +943,11 @@ class scoped_allocator_adaptor_base return *this; } + void swap(scoped_allocator_adaptor_base &r) + { + boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator()); + } + inner_allocator_type& inner_allocator() { return static_cast(*this); } @@ -1158,6 +1175,18 @@ class scoped_allocator_adaptor return *this; } + //! Effects: swaps *this with r. + //! + void swap(scoped_allocator_adaptor &r) + { + base_type::swap(r); + } + + //! Effects: swaps *this with r. + //! + friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r) + { l.swap(r); } + //! Returns: //! `static_cast(*this)`. outer_allocator_type & outer_allocator() diff --git a/include/boost/container/static_vector.hpp b/include/boost/container/static_vector.hpp index 020a208..fb97b7f 100644 --- a/include/boost/container/static_vector.hpp +++ b/include/boost/container/static_vector.hpp @@ -21,34 +21,6 @@ namespace boost { namespace container { -/** - * @defgroup static_vector_non_member static_vector non-member functions - */ - -/** - * @brief A variable-size array container with fixed capacity. - * - * static_vector is a sequence container like boost::container::vector with contiguous storage that can - * change in size, along with the static allocation, low overhead, and fixed capacity of boost::array. - * - * A static_vector is a sequence that supports random access to elements, constant time insertion and - * removal of elements at the end, and linear time insertion and removal of elements at the beginning or - * in the middle. The number of elements in a static_vector may vary dynamically up to a fixed capacity - * because elements are stored within the object itself similarly to an array. However, objects are - * initialized as they are inserted into static_vector unlike C arrays or std::array which must construct - * all elements on instantiation. The behavior of static_vector enables the use of statically allocated - * elements in cases with complex object lifetime requirements that would otherwise not be trivially - * possible. - * - * @par Error Handling - * Insertion beyond the capacity and out of bounds errors results in calling throw_bad_alloc(). - * The reason for this is because unlike vectors, static_vector does not perform allocation. - * - * @tparam Value The type of element that will be stored. - * @tparam Capacity The maximum number of elements static_vector can store, fixed at compile time. - */ - - namespace container_detail { template @@ -89,7 +61,32 @@ class static_storage_allocator } //namespace container_detail { +/** + * @defgroup static_vector_non_member static_vector non-member functions + */ +/** + * @brief A variable-size array container with fixed capacity. + * + * static_vector is a sequence container like boost::container::vector with contiguous storage that can + * change in size, along with the static allocation, low overhead, and fixed capacity of boost::array. + * + * A static_vector is a sequence that supports random access to elements, constant time insertion and + * removal of elements at the end, and linear time insertion and removal of elements at the beginning or + * in the middle. The number of elements in a static_vector may vary dynamically up to a fixed capacity + * because elements are stored within the object itself similarly to an array. However, objects are + * initialized as they are inserted into static_vector unlike C arrays or std::array which must construct + * all elements on instantiation. The behavior of static_vector enables the use of statically allocated + * elements in cases with complex object lifetime requirements that would otherwise not be trivially + * possible. + * + * @par Error Handling + * Insertion beyond the capacity and out of bounds errors results in calling throw_bad_alloc(). + * The reason for this is because unlike vectors, static_vector does not perform allocation. + * + * @tparam Value The type of element that will be stored. + * @tparam Capacity The maximum number of elements static_vector can store, fixed at compile time. + */ template class static_vector : public vector > diff --git a/test/scoped_allocator_adaptor_test.cpp b/test/scoped_allocator_adaptor_test.cpp index 1855127..61e8c7b 100644 --- a/test/scoped_allocator_adaptor_test.cpp +++ b/test/scoped_allocator_adaptor_test.cpp @@ -9,6 +9,7 @@ ////////////////////////////////////////////////////////////////////////////// #include #include +#include #include #include #include @@ -461,6 +462,19 @@ int main() BOOST_STATIC_ASSERT(( Scoped2InnerTTT::propagate_on_container_swap::value )); } + //Default constructor + { + Scoped0Inner s0i; + Scoped1Inner s1i; + //Swap + { + Scoped0Inner s0i2; + Scoped1Inner s1i2; + boost::container::swap_dispatch(s0i, s0i2); + boost::container::swap_dispatch(s1i, s1i2); + } + } + //Default constructor { Scoped0Inner s0i; From 3c35c4e4f69fda245a742349c697fe1ccc755e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 8 Jun 2013 22:05:49 +0000 Subject: [PATCH 02/26] Update aknowledgements section [SVN r84702] --- doc/container.qbk | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/container.qbk b/doc/container.qbk index 2c3dd4e..8a043a9 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -648,6 +648,9 @@ 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. +* `static_vector` was based on Andrew Hundt's and Adam Wulkiewicz's high-performance `varray` class. + Many performance improvements of `vector` were also inspired in their implementation. Thanks! + * 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. @@ -661,6 +664,8 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes_boost_1_54_00 Boost 1.54 Release] +* Added experimental `static_vector` class, based on Andrew Hundt's and Adam Wulkiewicz's + high performance `varray` class. * Speed improvements in `vector` constructors/copy/move/swap, dispatching to memcpy when possible. * Support for `BOOST_NO_EXCEPTIONS` [@https://svn.boost.org/trac/boost/ticket/7227 #7227]. * Fixed bugs [@https://svn.boost.org/trac/boost/ticket/7921 #7921], @@ -668,7 +673,6 @@ use [*Boost.Container]? There are several reasons for that: [@https://svn.boost.org/trac/boost/ticket/8118 #8118], [@https://svn.boost.org/trac/boost/ticket/8294 #8294], [@https://svn.boost.org/trac/boost/ticket/8553 #8553]. -* Added experimental `static_vector` class. [endsect] From b0f89115b349732a0e399c94654274a4c7b6f7c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 8 Jun 2013 22:54:27 +0000 Subject: [PATCH 03/26] Added `static_vector` to non-standard containers section. [SVN r84705] --- doc/container.qbk | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/doc/container.qbk b/doc/container.qbk index 8a043a9..2018ed5 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -236,7 +236,7 @@ a throw callback declared in ``: [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] +This useful, fully STL-compliant stable container [@http://bannalia.blogspot.com/2008/09/introducing-stablevector.html designed 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]. @@ -432,6 +432,32 @@ complementary. [endsect] +[section:static_vector ['static_vector]] + +`static_vector` is an hybrid between `vector` and `array`: like `vector`, it's a sequence container +with contiguous storage that can change in size, along with the static allocation, low overhead, +and fixed capacity of `array`. `static_vector` is based on Adam Wulkiewicz and Andrew Hundt's +high-performance [@https://svn.boost.org/svn/boost/sandbox/varray/doc/html/index.html varray] +class. + +The number of elements in a `static_vector` may vary dynamically up to a fixed capacity +because elements are stored within the object itself similarly to an array. However, objects are +initialized as they are inserted into `static_vector` unlike C arrays or `std::array` which must construct +all elements on instantiation. The behavior of `static_vector` enables the use of statically allocated +elements in cases with complex object lifetime requirements that would otherwise not be trivially +possible. Some other properties: + +* Random access to elements +* Constant time insertion and removal of elements at the end +* Linear time insertion and removal of elements at the beginning or in the middle. + +`static_vector` is well suited for use in a buffer, the internal implementation of other +classes, or use cases where there is a fixed limit to the number of elements that must be stored. +Embedded and realtime applications where allocation either may not be available or acceptable +are a particular case where `static_vector` can be beneficial. + +[endsect] + [endsect] [section:Cpp11_conformance C++11 Conformance] From f7accef426878c55da4ad2d5362533222fca53e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 24 Jun 2013 19:10:07 +0000 Subject: [PATCH 04/26] Trivial fix for empty ranges in node_alloc_holder [SVN r84900] --- .../container/detail/node_alloc_holder.hpp | 80 ++++++++++--------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index 7d851c0..5a94a68 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -229,48 +229,50 @@ struct node_alloc_holder void allocate_many_and_construct (FwdIterator beg, difference_type n, Inserter inserter) { - /* - NodePtr p = this->allocate_one(); - Deallocator node_deallocator(p, this->node_alloc()); - ::boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), it); - node_deallocator.release(); - //This does not throw - typedef typename Node::hook_type hook_type; - ::new(static_cast(container_detail::to_raw_pointer(p))) hook_type; - return (p); - */ - typedef typename NodeAlloc::multiallocation_chain multiallocation_chain; + if(n){ + /* + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + ::boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), it); + node_deallocator.release(); + //This does not throw + typedef typename Node::hook_type hook_type; + ::new(static_cast(container_detail::to_raw_pointer(p))) hook_type; + return (p); + */ + typedef typename NodeAlloc::multiallocation_chain multiallocation_chain; - //Try to allocate memory in a single block - typedef typename multiallocation_chain::iterator multialloc_iterator; - multiallocation_chain mem; - this->node_alloc().allocate_individual(n, mem); - multialloc_iterator itbeg(mem.begin()), itlast(mem.last()); - mem.clear(); - Node *p = 0; - NodeAlloc &nalloc = this->node_alloc(); - BOOST_TRY{ - while(n--){ - p = container_detail::to_raw_pointer(&*itbeg); - ++itbeg; - //This can throw - Deallocator node_deallocator(p, nalloc); - boost::container::construct_in_place(nalloc, container_detail::addressof(p->m_data), beg); - ++beg; - node_deallocator.release(); - //This does not throw - typedef typename Node::hook_type hook_type; - ::new(static_cast(p)) hook_type; - //This can throw in some containers (predicate might throw) - inserter(*p); + //Try to allocate memory in a single block + typedef typename multiallocation_chain::iterator multialloc_iterator; + multiallocation_chain mem; + this->node_alloc().allocate_individual(n, mem); + multialloc_iterator itbeg(mem.begin()), itlast(mem.last()); + mem.clear(); + Node *p = 0; + NodeAlloc &nalloc = this->node_alloc(); + BOOST_TRY{ + while(n--){ + p = container_detail::to_raw_pointer(&*itbeg); + ++itbeg; + //This can throw + Deallocator node_deallocator(p, nalloc); + boost::container::construct_in_place(nalloc, container_detail::addressof(p->m_data), beg); + ++beg; + node_deallocator.release(); + //This does not throw + typedef typename Node::hook_type hook_type; + ::new(static_cast(p)) hook_type; + //This can throw in some containers (predicate might throw) + inserter(*p); + } } + BOOST_CATCH(...){ + mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n); + this->node_alloc().deallocate_individual(mem); + BOOST_RETHROW + } + BOOST_CATCH_END } - BOOST_CATCH(...){ - mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n); - this->node_alloc().deallocate_individual(mem); - BOOST_RETHROW - } - BOOST_CATCH_END } void clear(allocator_v1) From 8b60445c98f6a76466b8e15ad0c1a9d8830fd103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 24 Jun 2013 19:11:43 +0000 Subject: [PATCH 05/26] Trivial fix for empty ranges in node_alloc_holder [SVN r84901] --- doc/container.qbk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/container.qbk b/doc/container.qbk index 2018ed5..ff18ba4 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -698,7 +698,8 @@ use [*Boost.Container]? There are several reasons for that: [@https://svn.boost.org/trac/boost/ticket/7969 #7969], [@https://svn.boost.org/trac/boost/ticket/8118 #8118], [@https://svn.boost.org/trac/boost/ticket/8294 #8294], - [@https://svn.boost.org/trac/boost/ticket/8553 #8553]. + [@https://svn.boost.org/trac/boost/ticket/8553 #8553], + [@https://svn.boost.org/trac/boost/ticket/8724 #8724]. [endsect] From fa05d4447cb44252dada9663df738fe279169011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 28 Jul 2013 22:10:37 +0000 Subject: [PATCH 06/26] * Big refactoring in order to reduce template and debug symbol bloat. * Fixes #8698 * Implemented SCARY iterators [SVN r85165] --- include/boost/container/static_vector.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/boost/container/static_vector.hpp b/include/boost/container/static_vector.hpp index fb97b7f..4a8cce4 100644 --- a/include/boost/container/static_vector.hpp +++ b/include/boost/container/static_vector.hpp @@ -81,8 +81,11 @@ class static_storage_allocator * possible. * * @par Error Handling - * Insertion beyond the capacity and out of bounds errors results in calling throw_bad_alloc(). - * The reason for this is because unlike vectors, static_vector does not perform allocation. + * Insertion beyond the capacity result in throwing std::bad_alloc() if exceptions are enabled or + * calling throw_bad_alloc() if not enabled. + * + * std::out_of_range is thrown if out of bound access is performed in `at()` if exceptions are + * enabled, throw_out_of_range() if not enabled. * * @tparam Value The type of element that will be stored. * @tparam Capacity The maximum number of elements static_vector can store, fixed at compile time. From b1503a139e687f83ce90af96acaf6d4b6c3bdd90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 29 Jul 2013 21:32:23 +0000 Subject: [PATCH 07/26] Fixes #8892. [SVN r85167] --- include/boost/container/detail/flat_tree.hpp | 15 ++++-- .../container/detail/node_alloc_holder.hpp | 21 +++++---- include/boost/container/detail/tree.hpp | 47 +++++++++++-------- include/boost/container/flat_map.hpp | 20 +++++++- include/boost/container/flat_set.hpp | 21 ++++++++- include/boost/container/map.hpp | 24 +++++++++- include/boost/container/set.hpp | 14 ++++++ 7 files changed, 124 insertions(+), 38 deletions(-) diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 90f0352..2330d5b 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -115,7 +115,7 @@ class flat_tree : value_compare(), m_vect() {} - Data(const Data &d) + explicit Data(const Data &d) : value_compare(static_cast(d)), m_vect(d.m_vect) {} @@ -131,15 +131,18 @@ class flat_tree : value_compare(boost::move(static_cast(d))), m_vect(boost::move(d.m_vect), a) {} - Data(const Compare &comp) + explicit Data(const Compare &comp) : value_compare(comp), m_vect() {} - Data(const Compare &comp, - const allocator_t &alloc) + Data(const Compare &comp, const allocator_t &alloc) : value_compare(comp), m_vect(alloc) {} + explicit Data(const allocator_t &alloc) + : value_compare(), m_vect(alloc) + {} + Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d) { this->value_compare::operator=(d); @@ -203,6 +206,10 @@ class flat_tree : m_data(comp, a) { } + explicit flat_tree(const allocator_type& a) + : m_data(a) + { } + flat_tree(const flat_tree& x) : m_data(x.m_data) { } diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index 5a94a68..4a5052a 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -53,10 +53,14 @@ struct node_compare typedef typename ValueCompare::value_type value_type; typedef typename ValueCompare::key_of_value key_of_value; - node_compare(const ValueCompare &pred) + explicit node_compare(const ValueCompare &pred) : ValueCompare(pred) {} + node_compare() + : ValueCompare() + {} + ValueCompare &value_comp() { return static_cast(*this); } @@ -67,11 +71,10 @@ struct node_compare { return ValueCompare::operator()(a.get_data(), b.get_data()); } }; -template +template struct node_alloc_holder { typedef allocator_traits 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 @@ -116,20 +119,20 @@ struct node_alloc_holder { this->icont().swap(x.icont()); } //Constructors for associative containers - explicit node_alloc_holder(const ValAlloc &a, const Pred &c) + explicit node_alloc_holder(const ValAlloc &a, const ValPred &c) : members_(a, c) {} - explicit node_alloc_holder(const node_alloc_holder &x, const Pred &c) + explicit node_alloc_holder(const node_alloc_holder &x, const ValPred &c) : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c) {} - explicit node_alloc_holder(const Pred &c) + explicit node_alloc_holder(const ValPred &c) : members_(c) {} //helpers for move assignments - explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const Pred &c) + explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const ValPred &c) : members_(boost::move(x.node_alloc()), c) { this->icont().swap(x.icont()); } @@ -345,12 +348,12 @@ struct node_alloc_holder {} template - members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const Pred &c) + members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const ValPred &c) : NodeAlloc(boost::forward(c2alloc)) , m_icont(typename ICont::value_compare(c)) {} - explicit members_holder(const Pred &c) + explicit members_holder(const ValPred &c) : NodeAlloc() , m_icont(typename ICont::value_compare(c)) {} diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 9cb3c9f..138595e 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -50,8 +50,12 @@ struct tree_value_compare typedef KeyOfValue key_of_value; typedef Key key_type; - tree_value_compare(const key_compare &kcomp) - : key_compare(kcomp) + explicit tree_value_compare(const key_compare &kcomp) + : KeyCompare(kcomp) + {} + + tree_value_compare() + : KeyCompare() {} const key_compare &key_comp() const @@ -212,15 +216,15 @@ class rbtree , typename container_detail::intrusive_rbtree_type >::type - , KeyCompare + , tree_value_compare > { + typedef tree_value_compare + ValComp; typedef typename container_detail::intrusive_rbtree_type - < A, tree_value_compare - - >::type Icont; + < A, ValComp>::type Icont; typedef container_detail::node_alloc_holder - AllocHolder; + AllocHolder; typedef typename AllocHolder::NodePtr NodePtr; typedef rbtree < Key, Value, KeyOfValue , KeyCompare, A> ThisType; @@ -318,8 +322,7 @@ class rbtree typedef Value value_type; typedef A allocator_type; typedef KeyCompare key_compare; - typedef tree_value_compare< Key, Value - , KeyCompare, KeyOfValue> value_compare; + typedef ValComp value_compare; typedef typename boost::container:: allocator_traits::pointer pointer; typedef typename boost::container:: @@ -471,11 +474,15 @@ class rbtree typedef std::reverse_iterator const_reverse_iterator; rbtree() - : AllocHolder(key_compare()) + : AllocHolder(ValComp(key_compare())) {} - rbtree(const key_compare& comp, const allocator_type& a = allocator_type()) - : AllocHolder(a, comp) + explicit rbtree(const key_compare& comp, const allocator_type& a = allocator_type()) + : AllocHolder(a, ValComp(comp)) + {} + + explicit rbtree(const allocator_type& a) + : AllocHolder(a) {} template @@ -488,7 +495,7 @@ class rbtree >::type * = 0 #endif ) - : AllocHolder(a, comp) + : AllocHolder(a, value_compare(comp)) { if(unique_insertion){ this->insert_unique(first, last); @@ -508,7 +515,7 @@ class rbtree >::type * = 0 #endif ) - : AllocHolder(a, comp) + : AllocHolder(a, value_compare(comp)) { if(unique_insertion){ this->insert_unique(first, last); @@ -530,7 +537,7 @@ class rbtree >::type * = 0 #endif ) - : AllocHolder(a, comp) + : AllocHolder(a, value_compare(comp)) { this->insert_equal(first, last); } @@ -545,7 +552,7 @@ class rbtree >::type * = 0 #endif ) - : AllocHolder(a, comp) + : AllocHolder(a, value_compare(comp)) { //Optimized allocation and construction this->allocate_many_and_construct @@ -553,25 +560,25 @@ class rbtree } rbtree(const rbtree& x) - : AllocHolder(x, x.key_comp()) + : AllocHolder(x, x.value_comp()) { this->icont().clone_from (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); } rbtree(BOOST_RV_REF(rbtree) x) - : AllocHolder(::boost::move(static_cast(x)), x.key_comp()) + : AllocHolder(::boost::move(static_cast(x)), x.value_comp()) {} rbtree(const rbtree& x, const allocator_type &a) - : AllocHolder(a, x.key_comp()) + : AllocHolder(a, x.value_comp()) { this->icont().clone_from (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); } rbtree(BOOST_RV_REF(rbtree) x, const allocator_type &a) - : AllocHolder(a, x.key_comp()) + : AllocHolder(a, x.value_comp()) { if(this->node_alloc() == x.node_alloc()){ this->icont().swap(x.icont()); diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 8bb372f..ac48e6d 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -173,7 +173,15 @@ class flat_map //! //! Complexity: Constant. explicit flat_map(const Compare& comp, const allocator_type& a = allocator_type()) - : m_flat_tree(comp, container_detail::force(a)) {} + : m_flat_tree(comp, container_detail::force(a)) + {} + + //! Effects: Constructs an empty flat_map using the specified allocator. + //! + //! Complexity: Constant. + explicit flat_map(const allocator_type& a) + : m_flat_tree(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 ). @@ -1024,7 +1032,15 @@ class flat_multimap //! Complexity: Constant. explicit flat_multimap(const Compare& comp, const allocator_type& a = allocator_type()) - : m_flat_tree(comp, container_detail::force(a)) { } + : m_flat_tree(comp, container_detail::force(a)) + {} + + //! Effects: Constructs an empty flat_multimap using the specified allocator. + //! + //! Complexity: Constant. + explicit flat_multimap(const allocator_type& a) + : m_flat_tree(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 ). diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 82bdea8..7acee1c 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -121,6 +121,13 @@ class flat_set : m_flat_tree(comp, a) {} + //! Effects: Constructs an empty flat_set using the specified allocator. + //! + //! Complexity: Constant. + explicit flat_set(const allocator_type& a) + : m_flat_tree(a) + {} + //! Effects: Constructs an empty set using the specified comparison object and //! allocator, and inserts elements from the range [first ,last ). //! @@ -810,9 +817,21 @@ class flat_multiset : m_flat_tree() {} + //! Effects: Constructs an empty flat_multiset using the specified + //! comparison object and allocator. + //! + //! Complexity: Constant. explicit flat_multiset(const Compare& comp, const allocator_type& a = allocator_type()) - : m_flat_tree(comp, a) {} + : m_flat_tree(comp, a) + {} + + //! Effects: Constructs an empty flat_multiset using the specified allocator. + //! + //! Complexity: Constant. + explicit flat_multiset(const allocator_type& a) + : m_flat_tree(a) + {} template flat_multiset(InputIterator first, InputIterator last, diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index b1faf49..e6ca865 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -138,6 +138,16 @@ class map BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); } + //! Effects: Constructs an empty map using the specified allocator. + //! + //! Complexity: Constant. + explicit map(const allocator_type& a) + : m_tree(a) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); + } + //! Effects: Constructs an empty map using the specified comparison object and //! allocator, and inserts elements from the range [first ,last ). //! @@ -918,8 +928,7 @@ class multimap BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); } - //! Effects: Constructs an empty multimap using the specified comparison - //! object and allocator. + //! Effects: Constructs an empty multimap using the specified allocator. //! //! Complexity: Constant. explicit multimap(const Compare& comp, const allocator_type& a = allocator_type()) @@ -929,6 +938,17 @@ class multimap BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); } + //! Effects: Constructs an empty multimap using the specified comparison + //! object and allocator. + //! + //! Complexity: Constant. + explicit multimap(const allocator_type& a) + : m_tree(a) + { + //Allocator type must be std::pair + BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); + } + //! Effects: Constructs an empty multimap using the specified comparison object //! and allocator, and inserts elements from the range [first ,last ). //! diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 0b49376..7808859 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -113,6 +113,13 @@ class set : m_tree(comp, a) {} + //! Effects: Constructs an empty set using the specified allocator object. + //! + //! Complexity: Constant. + explicit set(const allocator_type& a) + : m_tree(a) + {} + //! Effects: Constructs an empty set using the specified comparison object and //! allocator, and inserts elements from the range [first ,last ). //! @@ -737,6 +744,13 @@ class multiset : m_tree(comp, a) {} + //! Effects: Constructs an empty multiset using the specified allocator. + //! + //! Complexity: Constant. + explicit multiset(const allocator_type& a) + : m_tree(a) + {} + //! Effects: Constructs an empty multiset using the specified comparison object //! and allocator, and inserts elements from the range [first ,last ). //! From 4e92a024fb505f89d1b36d92f73fcb9142647ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 29 Jul 2013 21:33:20 +0000 Subject: [PATCH 08/26] Fixes #8473 [SVN r85168] --- include/boost/container/detail/utilities.hpp | 4 ++++ include/boost/container/detail/workaround.hpp | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/include/boost/container/detail/utilities.hpp b/include/boost/container/detail/utilities.hpp index 81e0ed8..776a770 100644 --- a/include/boost/container/detail/utilities.hpp +++ b/include/boost/container/detail/utilities.hpp @@ -12,6 +12,7 @@ #define BOOST_CONTAINER_DETAIL_UTILITIES_HPP #include "config_begin.hpp" +#include "workaround.hpp" #include #include //for ::memcpy #include @@ -1055,18 +1056,21 @@ inline typename container_detail::enable_if_c ::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; + BOOST_CONTAINER_FALLTHOUGH case 3: ::memcpy(stora_ptr, large_ptr, sizeof_storage); ::memcpy(large_ptr, short_ptr, sizeof_storage); ::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; + BOOST_CONTAINER_FALLTHOUGH case 2: ::memcpy(stora_ptr, large_ptr, sizeof_storage); ::memcpy(large_ptr, short_ptr, sizeof_storage); ::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; + BOOST_CONTAINER_FALLTHOUGH case 1: ::memcpy(stora_ptr, large_ptr, sizeof_storage); ::memcpy(large_ptr, short_ptr, sizeof_storage); diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp index 06cb733..49fe284 100644 --- a/include/boost/container/detail/workaround.hpp +++ b/include/boost/container/detail/workaround.hpp @@ -35,6 +35,12 @@ #define BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST #endif +#if !defined(BOOST_FALLTHOUGH) + #define BOOST_CONTAINER_FALLTHOUGH +#else + #define BOOST_CONTAINER_FALLTHOUGH BOOST_FALLTHOUGH; +#endif + //Macros for documentation purposes. For code, expands to the argument #define BOOST_CONTAINER_IMPDEF(TYPE) TYPE #define BOOST_CONTAINER_SEEDOC(TYPE) TYPE From db9dfed10717c86533c91de7a048c554fdca2467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 29 Jul 2013 21:40:30 +0000 Subject: [PATCH 09/26] Test update for #8892 + changelog updated. [SVN r85169] --- doc/container.qbk | 7 +++++++ test/flat_tree_test.cpp | 7 +++++++ test/tree_test.cpp | 8 +++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/doc/container.qbk b/doc/container.qbk index ff18ba4..bc65a48 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -688,6 +688,13 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes Release Notes] +[section:release_notes_boost_1_55_00 Boost 1.55 Release] + +* Fixed bugs [@https://svn.boost.org/trac/boost/ticket/8892 #8892], + [@https://svn.boost.org/trac/boost/ticket/8473 #8473]. + +[endsect] + [section:release_notes_boost_1_54_00 Boost 1.54 Release] * Added experimental `static_vector` class, based on Andrew Hundt's and Adam Wulkiewicz's diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp index 5854b59..146285c 100644 --- a/test/flat_tree_test.cpp +++ b/test/flat_tree_test.cpp @@ -475,6 +475,13 @@ int main() { using namespace boost::container::test; + //Allocator argument container + { + flat_set set_((std::allocator())); + flat_multiset multiset_((std::allocator())); + flat_map map_((std::allocator >())); + flat_multimap multimap_((std::allocator >())); + } //Now test move semantics { test_move >(); diff --git a/test/tree_test.cpp b/test/tree_test.cpp index dca5a31..60d593f 100644 --- a/test/tree_test.cpp +++ b/test/tree_test.cpp @@ -247,6 +247,13 @@ int main () map map_; multimap multimap_; } + //Allocator argument container + { + set set_((std::allocator())); + multiset multiset_((std::allocator())); + map map_((std::allocator >())); + multimap multimap_((std::allocator >())); + } //Now test move semantics { test_move >(); @@ -255,7 +262,6 @@ int main () test_move >(); } - //using namespace boost::container::detail; if(0 != test::set_test Date: Sat, 10 Aug 2013 22:58:27 +0000 Subject: [PATCH 10/26] Fixes #8269 [SVN r85297] --- doc/container.qbk | 3 ++- include/boost/container/flat_map.hpp | 13 ++++++++++++- include/boost/container/flat_set.hpp | 17 +++++++++-------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index bc65a48..1c77c07 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -375,7 +375,8 @@ and erasure times considerably. Flat associative containers have the following attributes: * Faster lookup than standard associative containers -* Much faster iteration than standard associative containers +* Much faster iteration than standard associative containers. + Random-access iterators instead of bidirectional iterators. * 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) diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index ac48e6d..da992aa 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -84,8 +84,10 @@ static D force_copy(S s) //! This means that inserting a new element into a flat_map invalidates //! previous iterators and references //! -//! Erasing an element of a flat_map invalidates iterators and references +//! Erasing an element invalidates iterators and references //! pointing to elements that come after (their keys are bigger) the erased element. +//! +//! This container provides random-access iterators. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED template , class Allocator = std::allocator< std::pair< Key, T> > > #else @@ -947,6 +949,15 @@ inline bool operator<(const flat_multimap& x, //! //! Allocator is the allocator to allocate the value_types //! (e.g. allocator< std::pair >). +//! +//! flat_multimap is similar to std::multimap but it's implemented like an ordered vector. +//! This means that inserting a new element into a flat_map invalidates +//! previous iterators and references +//! +//! Erasing an element invalidates iterators and references +//! pointing to elements that come after (their keys are bigger) the erased element. +//! +//! This container provides random-access iterators. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED template , class Allocator = std::allocator< std::pair< Key, T> > > #else diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 7acee1c..eed7dda 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -51,9 +51,7 @@ inline bool operator<(const flat_set& x, /// @endcond //! flat_set is a Sorted Associative Container that stores objects of type Key. -//! flat_set is a Simple Associative Container, meaning that its value type, -//! as well as its key type, is Key. It is also a Unique Associative Container, -//! meaning that no two elements are the same. +//! It is also a Unique Associative Container, meaning that no two elements are the same. //! //! flat_set is similar to std::set but it's implemented like an ordered vector. //! This means that inserting a new element into a flat_set invalidates @@ -61,6 +59,8 @@ inline bool operator<(const flat_set& x, //! //! Erasing an element of a flat_set invalidates iterators and references //! pointing to elements that come after (their keys are bigger) the erased element. +//! +//! This container provides random-access iterators. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED template , class Allocator = std::allocator > #else @@ -763,16 +763,17 @@ inline bool operator<(const flat_multiset& x, /// @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 can store multiple copies of the same key value. //! //! flat_multiset is similar to std::multiset but it's implemented like an ordered vector. //! This means that inserting a new element into a flat_multiset invalidates //! previous iterators and references //! -//! Erasing an element of a flat_multiset invalidates iterators and references -//! pointing to elements that come after (their keys are equal or bigger) the erased element. +//! Erasing an element invalidates iterators and references +//! pointing to elements that come after (their keys are bigger) the erased element. +//! +//! This container provides random-access iterators. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED template , class Allocator = std::allocator > #else From 3d249fa7280d6e142b3017ccf5677337cb6a9029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 11 Aug 2013 21:36:19 +0000 Subject: [PATCH 11/26] Implemented SCARY iterators for all containers [SVN r85308] --- doc/container.qbk | 68 ++- include/boost/container/deque.hpp | 502 +++++++++---------- include/boost/container/detail/flat_tree.hpp | 4 +- include/boost/container/detail/iterators.hpp | 97 +++- include/boost/container/detail/tree.hpp | 98 +--- include/boost/container/list.hpp | 115 +---- include/boost/container/slist.hpp | 101 +--- include/boost/container/stable_vector.hpp | 174 +++---- include/boost/container/vector.hpp | 163 +++--- test/check_equal_containers.hpp | 2 - test/list_test.cpp | 8 +- test/slist_test.cpp | 9 - test/stable_vector_test.cpp | 6 +- test/vector_test.cpp | 4 +- 14 files changed, 559 insertions(+), 792 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 1c77c07..2c66420 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2009-2012 Ion Gazta\u00F1aga + / Copyright (c) 2009-2013 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) @@ -8,7 +8,7 @@ [library Boost.Container [quickbook 1.5] [authors [Gaztanaga, Ion]] - [copyright 2009-2012 Ion Gaztanaga] + [copyright 2009-2013 Ion Gaztanaga] [id container] [dirname container] [purpose Containers library] @@ -67,6 +67,8 @@ compiler include path. [endsect] +[section:main_features Main features] + [section:move_emplace Efficient insertion] Move semantics and placement insertion are two features brought by C++11 containers @@ -189,6 +191,45 @@ Finally, we can just compile, link, and run! [endsect] +[section:scary_iterators SCARY iterators] + +The paper N2913, titled [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2913.pdf, +SCARY Iterator Assignment and Initialization], proposed a requirement that a standard container's +iterator types have no dependency on any type argument apart from the container's `value_type`, +`difference_type`, `pointer type`, and `const_pointer` type. In particular, according to the proposal, +the types of a standard container's iterators should not depend on the container's `key_compare`, +`hasher`, `key_equal`, or `allocator` types. + +That paper demonstrated that SCARY operations were crucial to the performant implementation of common +design patterns using STL components. It showed that implementations that support SCARY operations reduce +object code bloat by eliminating redundant specializations of iterator and algorithm templates. + +[*Boost.Container] containers implement SCARY iterators so the iterator type of a container is only dependent +on the `allocator_traits::pointer` type (the pointer type of the `value_type` to be inserted +in the container). Reference types and all other typedefs are deduced from the pointer type using the +C++11 `pointer_traits` utility. This leads to lower code bloat in algorithms and classes templated on +iterators. + +[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 tree nodes + in the parent pointer. + +* `[multi]set/map` containers use no recursive functions so stack problems are avoided. + +[endsect] + +[endsect] + [section:exception_handling Boost.Container and C++ exceptions] In some environments, such as game development or embedded systems, C++ exceptions are disabled or a customized error handling is needed. @@ -525,7 +566,7 @@ elements' elements, and so on. [*Boost.Container] implements its own `scoped_allocator_adaptor` class and [*backports this feature also to C++03 compilers]. Due to C++03 limitations, in those compilers the allocator propagation implemented by `scoped_allocator_adaptor::construct` functions -will be based on traits([classref boost::container::constructible_with_allocator_suffix constructible_with_allocator_suffix] +will be based on traits ([classref boost::container::constructible_with_allocator_suffix constructible_with_allocator_suffix] and [classref boost::container::constructible_with_allocator_prefix constructible_with_allocator_prefix]) proposed in [@http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2008/n2554.pdf N2554: The Scoped Allocator Model (Rev 2) proposal]. In conforming C++11 compilers or compilers supporting SFINAE @@ -582,22 +623,6 @@ If you need a memory optimized version of `boost::container::vector` funct [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 tree nodes - in 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] @@ -691,8 +716,11 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes_boost_1_55_00 Boost 1.55 Release] +* Implemented [link container.main_features.scary_iterators SCARY iterators]. + * Fixed bugs [@https://svn.boost.org/trac/boost/ticket/8892 #8892], - [@https://svn.boost.org/trac/boost/ticket/8473 #8473]. + [@https://svn.boost.org/trac/boost/ticket/8473 #8473], + [@https://svn.boost.org/trac/boost/ticket/8269 #8269]. [endsect] diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index 5ff423d..986b62f 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -75,11 +75,10 @@ template #endif class deque; -template +template struct deque_value_traits { typedef T value_type; - typedef Allocator allocator_type; static const bool trivial_dctr = boost::has_trivial_destructor::value; static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move::value; static const bool trivial_copy = has_trivial_copy::value; @@ -91,13 +90,211 @@ struct deque_value_traits // Note: this function is simply a kludge to work around several compilers' // bugs in handling constant expressions. -inline std::size_t deque_buf_size(std::size_t size) - { return size < 512 ? std::size_t(512 / size) : std::size_t(1); } +template +struct deque_buf_size +{ + static const std::size_t min_size = 512u; + static const std::size_t sizeof_t = sizeof(T); + static const std::size_t value = sizeof_t < min_size ? (min_size/sizeof_t) : std::size_t(1); +}; + +namespace container_detail { + +// Class invariants: +// For any nonsingular iterator i: +// i.node is the address of an element in the map array. The +// contents of i.node is a pointer to the beginning of a node. +// i.first == //(i.node) +// i.last == i.first + node_size +// i.cur is a pointer in the range [i.first, i.last). NOTE: +// the implication of this is that i.cur is always a dereferenceable +// pointer, even if i is a past-the-end iterator. +// Start and Finish are always nonsingular iterators. NOTE: this means +// that an empty deque must have one node, and that a deque +// with N elements, where N is the buffer size, must have two nodes. +// For every node other than start.node and finish.node, every element +// in the node is an initialized object. If start.node == finish.node, +// then [start.cur, finish.cur) are initialized objects, and +// the elements outside that range are uninitialized storage. Otherwise, +// [start.cur, start.last) and [finish.first, finish.cur) are initialized +// objects, and [start.first, start.cur) and [finish.cur, finish.last) +// are uninitialized storage. +// [map, map + map_size) is a valid, non-empty range. +// [start.node, finish.node] is a valid range contained within +// [map, map + map_size). +// Allocator pointer in the range [map, map + map_size) points to an allocated node +// if and only if the pointer is in the range [start.node, finish.node]. +template +class deque_iterator +{ + public: + 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 if_c + < IsConst + , typename boost::intrusive::pointer_traits::template + rebind_pointer::type + , Pointer + >::type pointer; + typedef typename if_c + < IsConst + , const value_type& + , value_type& + >::type reference; + + static std::size_t s_buffer_size() + { return deque_buf_size::value; } + + typedef Pointer val_alloc_ptr; + typedef typename boost::intrusive::pointer_traits:: + template rebind_pointer::type index_pointer; + + Pointer m_cur; + Pointer m_first; + Pointer m_last; + index_pointer m_node; + + public: + + Pointer get_cur() const { return m_cur; } + Pointer get_first() const { return m_first; } + Pointer get_last() const { return m_last; } + index_pointer get_node() const { return m_node; } + + deque_iterator(val_alloc_ptr x, index_pointer y) BOOST_CONTAINER_NOEXCEPT + : m_cur(x), m_first(*y), m_last(*y + s_buffer_size()), m_node(y) + {} + + deque_iterator() BOOST_CONTAINER_NOEXCEPT + : m_cur(), m_first(), m_last(), m_node() + {} + + deque_iterator(deque_iterator const& x) BOOST_CONTAINER_NOEXCEPT + : m_cur(x.get_cur()), m_first(x.get_first()), m_last(x.get_last()), m_node(x.get_node()) + {} + + deque_iterator(Pointer cur, Pointer first, Pointer last, index_pointer node) BOOST_CONTAINER_NOEXCEPT + : m_cur(cur), m_first(first), m_last(last), m_node(node) + {} + + deque_iterator unconst() const BOOST_CONTAINER_NOEXCEPT + { + return deque_iterator(this->get_cur(), this->get_first(), this->get_last(), this->get_node()); + } + + reference operator*() const BOOST_CONTAINER_NOEXCEPT + { return *this->m_cur; } + + pointer operator->() const BOOST_CONTAINER_NOEXCEPT + { return this->m_cur; } + + difference_type operator-(const deque_iterator& x) const BOOST_CONTAINER_NOEXCEPT + { + if(!this->m_cur && !x.m_cur){ + return 0; + } + return difference_type(this->s_buffer_size()) * (this->m_node - x.m_node - 1) + + (this->m_cur - this->m_first) + (x.m_last - x.m_cur); + } + + deque_iterator& operator++() BOOST_CONTAINER_NOEXCEPT + { + ++this->m_cur; + if (this->m_cur == this->m_last) { + this->priv_set_node(this->m_node + 1); + this->m_cur = this->m_first; + } + return *this; + } + + deque_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT + { + deque_iterator tmp(*this); + ++*this; + return tmp; + } + + deque_iterator& operator--() BOOST_CONTAINER_NOEXCEPT + { + if (this->m_cur == this->m_first) { + this->priv_set_node(this->m_node - 1); + this->m_cur = this->m_last; + } + --this->m_cur; + return *this; + } + + deque_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT + { + deque_iterator tmp(*this); + --*this; + return tmp; + } + + deque_iterator& operator+=(difference_type n) BOOST_CONTAINER_NOEXCEPT + { + difference_type offset = n + (this->m_cur - this->m_first); + if (offset >= 0 && offset < difference_type(this->s_buffer_size())) + this->m_cur += n; + else { + difference_type node_offset = + offset > 0 ? offset / difference_type(this->s_buffer_size()) + : -difference_type((-offset - 1) / this->s_buffer_size()) - 1; + this->priv_set_node(this->m_node + node_offset); + this->m_cur = this->m_first + + (offset - node_offset * difference_type(this->s_buffer_size())); + } + return *this; + } + + deque_iterator operator+(difference_type n) const BOOST_CONTAINER_NOEXCEPT + { deque_iterator tmp(*this); return tmp += n; } + + deque_iterator& operator-=(difference_type n) BOOST_CONTAINER_NOEXCEPT + { return *this += -n; } + + deque_iterator operator-(difference_type n) const BOOST_CONTAINER_NOEXCEPT + { deque_iterator tmp(*this); return tmp -= n; } + + reference operator[](difference_type n) const BOOST_CONTAINER_NOEXCEPT + { return *(*this + n); } + + friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_cur == r.m_cur; } + + friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_cur != r.m_cur; } + + friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return (l.m_node == r.m_node) ? (l.m_cur < r.m_cur) : (l.m_node < r.m_node); } + + friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return r < l; } + + friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return !(r < l); } + + friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return !(l < r); } + + void priv_set_node(index_pointer new_node) BOOST_CONTAINER_NOEXCEPT + { + this->m_node = new_node; + this->m_first = *new_node; + this->m_last = this->m_first + this->s_buffer_size(); + } + + friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_CONTAINER_NOEXCEPT + { return x += n; } +}; + +} //namespace container_detail { // Deque base class. It has two purposes. First, its constructor // and destructor allocate (but don't initialize) storage. This makes // exception safety easier. -template +template class deque_base { BOOST_COPYABLE_AND_MOVABLE(deque_base) @@ -124,257 +321,26 @@ class deque_base protected: - typedef deque_value_traits traits_t; - typedef ptr_alloc_t 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)); } + static size_type s_buffer_size() BOOST_CONTAINER_NOEXCEPT + { return deque_buf_size::value; } val_alloc_ptr priv_allocate_node() { return this->alloc().allocate(s_buffer_size()); } - void priv_deallocate_node(val_alloc_ptr p) + void priv_deallocate_node(val_alloc_ptr p) BOOST_CONTAINER_NOEXCEPT { 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) + void priv_deallocate_map(ptr_alloc_ptr p, size_type n) BOOST_CONTAINER_NOEXCEPT { 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). - // Allocator pointer in the range [map, map + map_size) points to an allocated node - // if and only if the pointer is in the range [start.node, finish.node]. - 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 + 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; } - }; + typedef container_detail::deque_iterator iterator; + typedef container_detail::deque_iterator const_iterator; deque_base(size_type num_elements, const allocator_type& a) : members_(a) @@ -406,7 +372,7 @@ class deque_base protected: - void swap_members(deque_base &x) + void swap_members(deque_base &x) BOOST_CONTAINER_NOEXCEPT { std::swap(this->members_.m_start, x.members_.m_start); std::swap(this->members_.m_finish, x.members_.m_finish); @@ -458,13 +424,13 @@ class deque_base BOOST_CATCH_END } - void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) + void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) BOOST_CONTAINER_NOEXCEPT { for (ptr_alloc_ptr n = nstart; n < nfinish; ++n) this->priv_deallocate_node(*n); } - void priv_clear_map() + void priv_clear_map() BOOST_CONTAINER_NOEXCEPT { if (this->members_.m_map) { this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1); @@ -509,16 +475,16 @@ class deque_base iterator m_finish; } members_; - ptr_alloc_t &ptr_alloc() + ptr_alloc_t &ptr_alloc() BOOST_CONTAINER_NOEXCEPT { return members_; } - const ptr_alloc_t &ptr_alloc() const + const ptr_alloc_t &ptr_alloc() const BOOST_CONTAINER_NOEXCEPT { return members_; } - allocator_type &alloc() + allocator_type &alloc() BOOST_CONTAINER_NOEXCEPT { return members_; } - const allocator_type &alloc() const + const allocator_type &alloc() const BOOST_CONTAINER_NOEXCEPT { return members_; } }; /// @endcond @@ -530,11 +496,11 @@ template > #else template #endif -class deque : protected deque_base +class deque : protected deque_base { /// @cond private: - typedef deque_base Base; + typedef deque_base Base; /// @endcond public: @@ -1397,7 +1363,7 @@ class deque : protected deque_base ) { size_type n = 0; - iterator it(pos); + iterator it(pos.unconst()); for(;first != last; ++first, ++n){ it = this->emplace(it, *first); ++it; @@ -1468,15 +1434,15 @@ class deque : protected deque_base //! Constant if pos is the first or the last element. iterator erase(const_iterator pos) BOOST_CONTAINER_NOEXCEPT { - const_iterator next = pos; + iterator next = pos.unconst(); ++next; size_type index = pos - this->members_.m_start; if (index < (this->size()/2)) { - boost::move_backward(begin(), iterator(pos), iterator(next)); + boost::move_backward(this->begin(), pos.unconst(), next); pop_front(); } else { - boost::move(iterator(next), end(), iterator(pos)); + boost::move(next, this->end(), pos.unconst()); pop_back(); } return this->members_.m_start + index; @@ -1500,7 +1466,7 @@ class deque : protected deque_base const size_type n = static_cast(last - first); const size_type elems_before = static_cast(first - this->members_.m_start); if (elems_before < (this->size() - n) - elems_before) { - boost::move_backward(begin(), iterator(first), iterator(last)); + boost::move_backward(begin(), first.unconst(), last.unconst()); iterator new_start = this->members_.m_start + n; if(!Base::traits_t::trivial_dctr_after_move) this->priv_destroy_range(this->members_.m_start, new_start); @@ -1508,7 +1474,7 @@ class deque : protected deque_base this->members_.m_start = new_start; } else { - boost::move(iterator(last), end(), iterator(first)); + boost::move(last.unconst(), end(), first.unconst()); iterator new_finish = this->members_.m_finish - n; if(!Base::traits_t::trivial_dctr_after_move) this->priv_destroy_range(new_finish, this->members_.m_finish); @@ -1674,7 +1640,7 @@ class deque : protected deque_base template iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy interf) { - iterator pos(p); + iterator pos(p.unconst()); const size_type pos_n = p - this->cbegin(); if(!this->members_.m_map){ this->priv_initialize_map(0); @@ -1845,7 +1811,7 @@ class deque : protected deque_base } // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first. - void priv_pop_back_aux() + void priv_pop_back_aux() BOOST_CONTAINER_NOEXCEPT { this->priv_deallocate_node(this->members_.m_finish.m_first); this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1); @@ -1860,7 +1826,7 @@ class deque : protected deque_base // if the deque has at least one element (a precondition for this member // function), and if this->members_.m_start.m_cur == this->members_.m_start.m_last, then the deque // must have at least two nodes. - void priv_pop_front_aux() + void priv_pop_front_aux() BOOST_CONTAINER_NOEXCEPT { allocator_traits_type::destroy ( this->alloc() @@ -1959,31 +1925,31 @@ class deque : protected deque_base // Nonmember functions. template -inline bool operator==(const deque& x, const deque& y) +inline bool operator==(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return x.size() == y.size() && equal(x.begin(), x.end(), y.begin()); } template -inline bool operator<(const deque& x, const deque& y) +inline bool operator<(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } template -inline bool operator!=(const deque& x, const deque& y) +inline bool operator!=(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return !(x == y); } template -inline bool operator>(const deque& x, const deque& y) +inline bool operator>(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return y < x; } template -inline bool operator>=(const deque& x, const deque& y) +inline bool operator>=(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return !(x < y); } template -inline bool operator<=(const deque& x, const deque& y) +inline bool operator<=(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return !(y < x); } template diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 2330d5b..896f161 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -85,9 +85,9 @@ struct get_flat_tree_iterators rebind_pointer::type const_iterator; #else //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER typedef typename container_detail:: - vector_iterator iterator; + vec_iterator iterator; typedef typename container_detail:: - vector_const_iterator const_iterator; + vec_iterator const_iterator; #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; diff --git a/include/boost/container/detail/iterators.hpp b/include/boost/container/detail/iterators.hpp index bba7205..03ac6c9 100644 --- a/include/boost/container/detail/iterators.hpp +++ b/include/boost/container/detail/iterators.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef BOOST_CONTAINER_PERFECT_FORWARDING #include @@ -585,24 +586,112 @@ struct is_bidirectional_iterator static const bool value = false; }; -template +template struct iiterator_types { + typedef typename IIterator::value_type it_value_type; + typedef typename it_value_type::value_type value_type; typedef typename std::iterator_traits::pointer it_pointer; typedef typename std::iterator_traits::difference_type difference_type; typedef typename ::boost::intrusive::pointer_traits:: - template rebind_pointer::type pointer; + template rebind_pointer::type pointer; typedef typename ::boost::intrusive::pointer_traits:: - template rebind_pointer::type const_pointer; + template rebind_pointer::type const_pointer; typedef typename ::boost::intrusive:: pointer_traits::reference reference; typedef typename ::boost::intrusive:: pointer_traits::reference const_reference; + typedef typename IIterator::iterator_category iterator_category; }; +template +struct std_iterator +{ + typedef typename std::iterator + < typename iiterator_types::iterator_category + , typename iiterator_types::value_type + , typename iiterator_types::difference_type + , typename iiterator_types::const_pointer + , typename iiterator_types::const_reference> type; +}; + +template +struct std_iterator +{ + typedef typename std::iterator + < typename iiterator_types::iterator_category + , typename iiterator_types::value_type + , typename iiterator_types::difference_type + , typename iiterator_types::pointer + , typename iiterator_types::reference> type; +}; + +template +class iterator + : public std_iterator::type +{ + typedef typename std_iterator::type types_t; + + public: + typedef typename types_t::value_type value_type; + typedef typename types_t::pointer pointer; + typedef typename types_t::reference reference; + + iterator() + {} + + explicit iterator(IIterator iit) BOOST_CONTAINER_NOEXCEPT + : m_iit(iit) + {} + + iterator(iterator const& other) BOOST_CONTAINER_NOEXCEPT + : m_iit(other.get()) + {} + + iterator& operator++() BOOST_CONTAINER_NOEXCEPT + { ++this->m_iit; return *this; } + + iterator operator++(int) BOOST_CONTAINER_NOEXCEPT + { + iterator result (*this); + ++this->m_iit; + return result; + } + + iterator& operator--() BOOST_CONTAINER_NOEXCEPT + { + //If the iterator is not a bidirectional iterator, operator-- should not exist + BOOST_STATIC_ASSERT((is_bidirectional_iterator::value)); + --this->m_iit; return *this; + } + + iterator operator--(int) BOOST_CONTAINER_NOEXCEPT + { + iterator result (*this); + --this->m_iit; + return result; + } + + friend bool operator== (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_iit == r.m_iit; } + + friend bool operator!= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return !(l == r); } + + reference operator*() const BOOST_CONTAINER_NOEXCEPT + { return (*this->m_iit).get_data(); } + + pointer operator->() const BOOST_CONTAINER_NOEXCEPT + { return ::boost::intrusive::pointer_traits::pointer_to(this->operator*()); } + + const IIterator &get() const BOOST_CONTAINER_NOEXCEPT + { return this->m_iit; } + + private: + IIterator m_iit; +}; } //namespace container_detail { - } //namespace container { } //namespace boost { diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 138595e..6dcb1b7 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -20,8 +20,8 @@ #include #include #include - #include +#include #include #include #include @@ -376,100 +376,8 @@ class rbtree 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 boost::intrusive::pointer_traits::pointer_to(this->m_it->get_data()); } - - //Increment / Decrement - iterator& operator++() - { this->prot_incr(); return *this; } - - iterator operator++(int) - { iiterator tmp = this->m_it; ++*this; return iterator(tmp); } - - iterator& operator--() - { this->prot_decr(); return *this; } - - iterator operator--(int) - { iterator tmp = *this; --*this; return tmp; } - }; - + typedef container_detail::iterator iterator; + typedef container_detail::iterator const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 79f4a6b..e613f4a 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -26,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -64,8 +65,16 @@ struct list_node list_node(); public: + typedef T value_type; typedef typename list_hook::type hook_type; + T m_data; + + T &get_data() + { return this->m_data; } + + const T &get_data() const + { return this->m_data; } }; template @@ -89,105 +98,6 @@ struct intrusive_list_type typedef container_type type ; }; -template -class list_const_iterator - : public std::iterator< std::bidirectional_iterator_tag, T - , typename iiterator_types::difference_type - , typename iiterator_types::const_pointer - , typename iiterator_types::const_reference> -{ - protected: - - IIterator m_it; - - public: - typedef typename iiterator_types::const_pointer const_pointer; - typedef typename iiterator_types::const_reference const_reference; - - //Constructors - list_const_iterator() - : m_it() - {} - - explicit list_const_iterator(const IIterator &it) - : m_it(it) - {} - - //Pointer like operators - const_reference operator*() const - { return this->m_it->m_data; } - - const_pointer operator->() const - { return ::boost::intrusive::pointer_traits::pointer_to(this->m_it->m_data); } - - //Increment / Decrement - list_const_iterator& operator++() - { ++this->m_it; return *this; } - - list_const_iterator operator++(int) - { IIterator tmp = this->m_it; ++*this; return list_const_iterator(tmp); } - - list_const_iterator& operator--() - { --this->m_it; return *this; } - - list_const_iterator operator--(int) - { IIterator tmp = this->m_it; --*this; return list_const_iterator(tmp); } - - //Comparison operators - friend bool operator== (const list_const_iterator& l, const list_const_iterator& r) - { return l.m_it == r.m_it; } - - friend bool operator!= (const list_const_iterator& l, const list_const_iterator& r) - { return l.m_it != r.m_it; } - - const IIterator &get() const - { return this->m_it; } -}; - -template -class list_iterator - : public list_const_iterator -{ - private: - typedef list_const_iterator const_iterator; - - public: - typedef typename iiterator_types::pointer pointer; - typedef typename iiterator_types::reference reference; - - //Constructors - list_iterator() - : const_iterator() - {} - - explicit list_iterator(const IIterator &it) - : const_iterator(it) - {} - - //Pointer like operators - reference operator*() const - { return this->m_it->m_data; } - - pointer operator->() const - { return ::boost::intrusive::pointer_traits::pointer_to(this->m_it->m_data); } - - //Increment / Decrement - list_iterator& operator++() - { ++this->m_it; return *this; } - - list_iterator operator++(int) - { IIterator tmp = this->m_it; ++*this; return list_iterator(tmp); } - - list_iterator& operator--() - { --this->m_it; return *this; } - - list_iterator operator--(int) - { IIterator tmp = this->m_it; --*this; return list_iterator(tmp); } - - const IIterator &get() const - { return this->m_it; } -}; - } //namespace container_detail { /// @endcond @@ -255,8 +165,8 @@ class list BOOST_COPYABLE_AND_MOVABLE(list) - typedef container_detail::list_iterator iterator_impl; - typedef container_detail::list_const_iteratorconst_iterator_impl; + typedef container_detail::iterator iterator_impl; + typedef container_detail::iterator const_iterator_impl; /// @endcond public: @@ -442,7 +352,6 @@ class list } //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())); } diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index a9a4f67..e0aa95f 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -69,8 +70,16 @@ struct slist_node slist_node(); public: + typedef T value_type; typedef typename slist_hook::type hook_type; + T m_data; + + T &get_data() + { return this->m_data; } + + const T &get_data() const + { return this->m_data; } }; template @@ -95,93 +104,6 @@ struct intrusive_slist_type typedef container_type type ; }; -template -class slist_const_iterator - : public std::iterator< std::forward_iterator_tag, T - , typename iiterator_types::difference_type - , typename iiterator_types::const_pointer - , typename iiterator_types::const_reference> -{ - protected: - - IIterator m_it; - - public: - typedef typename iiterator_types::const_pointer const_pointer; - typedef typename iiterator_types::const_reference const_reference; - - //Constructors - slist_const_iterator() - : m_it() - {} - - explicit slist_const_iterator(const IIterator &it) - : m_it(it) - {} - - //Pointer like operators - const_reference operator*() const - { return this->m_it->m_data; } - - const_pointer operator->() const - { return ::boost::intrusive::pointer_traits::pointer_to(this->m_it->m_data); } - - //Increment / Decrement - slist_const_iterator& operator++() - { ++this->m_it; return *this; } - - slist_const_iterator operator++(int) - { IIterator tmp = this->m_it; ++*this; return slist_const_iterator(tmp); } - - //Comparison operators - friend bool operator== (const slist_const_iterator& l, const slist_const_iterator& r) - { return l.m_it == r.m_it; } - - friend bool operator!= (const slist_const_iterator& l, const slist_const_iterator& r) - { return l.m_it != r.m_it; } - - const IIterator &get() const - { return this->m_it; } -}; - -template -class slist_iterator - : public slist_const_iterator -{ - private: - typedef slist_const_iterator const_iterator; - - public: - typedef typename iiterator_types::pointer pointer; - typedef typename iiterator_types::reference reference; - - //Constructors - slist_iterator() - : const_iterator() - {} - - explicit slist_iterator(const IIterator &it) - : const_iterator(it) - {} - - //Pointer like operators - reference operator*() const - { return this->m_it->m_data; } - - pointer operator->() const - { return ::boost::intrusive::pointer_traits::pointer_to(this->m_it->m_data); } - - //Increment / Decrement - slist_iterator& operator++() - { ++this->m_it; return *this; } - - slist_iterator operator++(int) - { IIterator tmp = this->m_it; ++*this; return slist_iterator(tmp); } - - const IIterator &get() const - { return this->m_it; } -}; - } //namespace container_detail { /// @endcond @@ -271,8 +193,8 @@ class slist }; BOOST_COPYABLE_AND_MOVABLE(slist) - typedef container_detail::slist_iterator iterator_impl; - typedef container_detail::slist_const_iteratorconst_iterator_impl; + typedef container_detail::iterator iterator_impl; + typedef container_detail::iterator const_iterator_impl; /// @endcond public: @@ -451,7 +373,6 @@ class slist } //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())); } diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 3da8c64..c5353f3 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -88,7 +88,7 @@ class clear_on_destroy bool do_clear_; }; -template +template struct node; template @@ -116,167 +116,172 @@ struct node_base node_base_ptr_ptr up; }; -template +template struct node - : public node_base + : public node_base + ::template + rebind_pointer::type + > { private: node(); public: - T value; + typename ::boost::intrusive::pointer_traits::element_type value; }; -template +template class iterator - : public std::iterator< std::random_access_iterator_tag - , T - , typename boost::intrusive:: - pointer_traits::difference_type - , Pointer - , Reference> { - typedef boost::intrusive:: - pointer_traits ptr_traits; - typedef typename ptr_traits::template + typedef boost::intrusive::pointer_traits non_const_ptr_traits; + public: + typedef std::random_access_iterator_tag iterator_category; + typedef typename non_const_ptr_traits::element_type value_type; + typedef typename non_const_ptr_traits::difference_type difference_type; + typedef typename ::boost::container::container_detail::if_c + < IsConst + , typename non_const_ptr_traits::template + rebind_pointer::type + , Pointer + >::type pointer; + typedef typename ::boost::container::container_detail::if_c + < IsConst + , const value_type& + , value_type& + >::type reference; + + private: + typedef typename non_const_ptr_traits::template rebind_pointer::type void_ptr; - typedef node node_type; + typedef node node_type; typedef node_base node_base_type; - typedef typename ptr_traits::template + typedef typename non_const_ptr_traits::template rebind_pointer::type node_ptr; typedef boost::intrusive:: pointer_traits node_ptr_traits; - typedef typename ptr_traits::template + typedef typename non_const_ptr_traits::template rebind_pointer::type node_base_ptr; - typedef typename ptr_traits::template + typedef typename non_const_ptr_traits::template rebind_pointer::type node_base_ptr_ptr; - typedef typename ptr_traits::template - rebind_pointer::type friend_iterator_pointer; - friend class iterator; + node_ptr m_pn; public: - typedef std::random_access_iterator_tag iterator_category; - typedef T value_type; - typedef typename ptr_traits::difference_type difference_type; - typedef Pointer pointer; - typedef Reference reference; - iterator() + explicit iterator(node_ptr p) BOOST_CONTAINER_NOEXCEPT + : m_pn(p) {} - explicit iterator(node_ptr p) - : pn(p) + iterator() BOOST_CONTAINER_NOEXCEPT {} - iterator(const iterator& x) - : pn(x.pn) + iterator(iterator const& other) BOOST_CONTAINER_NOEXCEPT + : m_pn(other.node_pointer()) {} - node_ptr &node_pointer() - { return pn; } + node_ptr &node_pointer() BOOST_CONTAINER_NOEXCEPT + { return m_pn; } - const node_ptr &node_pointer() const - { return pn; } + const node_ptr &node_pointer() const BOOST_CONTAINER_NOEXCEPT + { return m_pn; } public: //Pointer like operators - reference operator*() const - { return pn->value; } + reference operator*() const BOOST_CONTAINER_NOEXCEPT + { return m_pn->value; } - pointer operator->() const - { return ptr_traits::pointer_to(this->operator*()); } + pointer operator->() const BOOST_CONTAINER_NOEXCEPT + { + typedef boost::intrusive::pointer_traits ptr_traits; + return ptr_traits::pointer_to(this->operator*()); + } //Increment / Decrement - iterator& operator++() + iterator& operator++() BOOST_CONTAINER_NOEXCEPT { - if(node_base_ptr_ptr p = this->pn->up){ + if(node_base_ptr_ptr p = this->m_pn->up){ ++p; - this->pn = node_ptr_traits::static_cast_from(*p); + this->m_pn = node_ptr_traits::static_cast_from(*p); } return *this; } - iterator operator++(int) + iterator operator++(int) BOOST_CONTAINER_NOEXCEPT { iterator tmp(*this); ++*this; return iterator(tmp); } - iterator& operator--() + iterator& operator--() BOOST_CONTAINER_NOEXCEPT { - if(node_base_ptr_ptr p = this->pn->up){ + if(node_base_ptr_ptr p = this->m_pn->up){ --p; - this->pn = node_ptr_traits::static_cast_from(*p); + this->m_pn = node_ptr_traits::static_cast_from(*p); } return *this; } - iterator operator--(int) + iterator operator--(int) BOOST_CONTAINER_NOEXCEPT { iterator tmp(*this); --*this; return iterator(tmp); } - reference operator[](difference_type off) const + reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT { iterator tmp(*this); tmp += off; return *tmp; } - iterator& operator+=(difference_type off) + iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT { - if(node_base_ptr_ptr p = this->pn->up){ + if(node_base_ptr_ptr p = this->m_pn->up){ p += off; - this->pn = node_ptr_traits::static_cast_from(*p); + this->m_pn = node_ptr_traits::static_cast_from(*p); } return *this; } - friend iterator operator+(const iterator &left, difference_type off) + friend iterator operator+(const iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT { iterator tmp(left); tmp += off; return tmp; } - friend iterator operator+(difference_type off, const iterator& right) + friend iterator operator+(difference_type off, const iterator& right) BOOST_CONTAINER_NOEXCEPT { iterator tmp(right); tmp += off; return tmp; } - iterator& operator-=(difference_type off) + iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT { *this += -off; return *this; } - friend iterator operator-(const iterator &left, difference_type off) + friend iterator operator-(const iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT { iterator tmp(left); tmp -= off; return tmp; } - friend difference_type operator-(const iterator& left, const iterator& right) - { - return left.pn->up - right.pn->up; - } + friend difference_type operator-(const iterator& left, const iterator& right) BOOST_CONTAINER_NOEXCEPT + { return left.m_pn->up - right.m_pn->up; } //Comparison operators - friend bool operator== (const iterator& l, const iterator& r) - { return l.pn == r.pn; } + friend bool operator== (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn == r.m_pn; } - friend bool operator!= (const iterator& l, const iterator& r) - { return l.pn != r.pn; } + friend bool operator!= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn != r.m_pn; } - friend bool operator< (const iterator& l, const iterator& r) - { return l.pn->up < r.pn->up; } + friend bool operator< (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn->up < r.m_pn->up; } - friend bool operator<= (const iterator& l, const iterator& r) - { return l.pn->up <= r.pn->up; } + friend bool operator<= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn->up <= r.m_pn->up; } - friend bool operator> (const iterator& l, const iterator& r) - { return l.pn->up > r.pn->up; } + friend bool operator> (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn->up > r.m_pn->up; } - friend bool operator>= (const iterator& l, const iterator& r) - { return l.pn->up >= r.pn->up; } - - node_ptr pn; + friend bool operator>= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn->up >= r.m_pn->up; } }; template @@ -354,7 +359,6 @@ struct index_traits } } - #ifdef STABLE_VECTOR_ENABLE_INVARIANT_CHECKING static bool invariants(index_type &index) { @@ -431,8 +435,10 @@ class stable_vector { ///@cond typedef allocator_traits allocator_traits_type; - typedef typename boost::intrusive::pointer_traits - :: + typedef boost::intrusive:: + pointer_traits + ptr_traits; + typedef typename ptr_traits:: template rebind_pointer::type void_ptr; typedef typename allocator_traits_type:: template portable_rebind_alloc @@ -451,10 +457,8 @@ class stable_vector typedef typename index_traits_type::index_iterator index_iterator; typedef typename index_traits_type:: const_index_iterator const_index_iterator; - typedef boost::intrusive:: - pointer_traits - ptr_traits; - typedef stable_vector_detail::node node_type; + typedef stable_vector_detail::node + node_type; typedef typename ptr_traits::template rebind_pointer::type node_ptr; typedef boost::intrusive:: @@ -495,13 +499,11 @@ class stable_vector friend class stable_vector_detail::clear_on_destroy; typedef stable_vector_detail::iterator - < T - , typename allocator_traits::reference - , typename allocator_traits::pointer> iterator_impl; + < typename allocator_traits::pointer + , false> iterator_impl; typedef stable_vector_detail::iterator - < T - , typename allocator_traits::const_reference - , typename allocator_traits::const_pointer> const_iterator_impl; + < typename allocator_traits::pointer + , false> const_iterator_impl; ///@endcond public: diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index dac536a..db41b60 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -61,20 +61,27 @@ namespace container_detail { #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER -//! Const vector_iterator used to iterate through a vector. -template -class vector_const_iterator +template +class vec_iterator { public: 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; + typedef typename if_c + < IsConst + , typename boost::intrusive::pointer_traits::template + rebind_pointer::type + , Pointer + >::type pointer; + typedef typename if_c + < IsConst + , const value_type& + , value_type& + >::type reference; /// @cond - protected: + private: Pointer m_ptr; public: @@ -84,7 +91,7 @@ class vector_const_iterator Pointer &get_ptr() BOOST_CONTAINER_NOEXCEPT { return m_ptr; } - explicit vector_const_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT + explicit vec_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT : m_ptr(ptr) {} /// @endcond @@ -92,7 +99,7 @@ class vector_const_iterator public: //Constructors - vector_const_iterator() BOOST_CONTAINER_NOEXCEPT + vec_iterator() BOOST_CONTAINER_NOEXCEPT #ifndef NDEBUG : m_ptr() #else @@ -100,139 +107,80 @@ class vector_const_iterator #endif {} + vec_iterator(vec_iterator const& other) BOOST_CONTAINER_NOEXCEPT + : m_ptr(other.get_ptr()) + {} + //Pointer like operators reference operator*() const BOOST_CONTAINER_NOEXCEPT { return *m_ptr; } - const value_type * operator->() const BOOST_CONTAINER_NOEXCEPT - { return container_detail::to_raw_pointer(m_ptr); } + pointer operator->() const BOOST_CONTAINER_NOEXCEPT + { return ::boost::intrusive::pointer_traits::pointer_to(this->operator*()); } reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT { return m_ptr[off]; } //Increment / Decrement - vector_const_iterator& operator++() BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator++() BOOST_CONTAINER_NOEXCEPT { ++m_ptr; return *this; } - vector_const_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT - { return vector_const_iterator(m_ptr++); } + vec_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT + { return vec_iterator(m_ptr++); } - vector_const_iterator& operator--() BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator--() BOOST_CONTAINER_NOEXCEPT { --m_ptr; return *this; } - vector_const_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT - { return vector_const_iterator(m_ptr--); } + vec_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT + { return vec_iterator(m_ptr--); } //Arithmetic - vector_const_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT { m_ptr += off; return *this; } - vector_const_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT { m_ptr -= off; return *this; } - friend vector_const_iterator operator+(const vector_const_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT - { return vector_const_iterator(x.m_ptr+off); } + friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT + { return vec_iterator(x.m_ptr+off); } - friend vector_const_iterator operator+(difference_type off, vector_const_iterator right) BOOST_CONTAINER_NOEXCEPT + friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_CONTAINER_NOEXCEPT { right.m_ptr += off; return right; } - friend vector_const_iterator operator-(vector_const_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT + friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT { left.m_ptr -= off; return left; } - friend difference_type operator-(const vector_const_iterator &left, const vector_const_iterator& right) BOOST_CONTAINER_NOEXCEPT + friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_CONTAINER_NOEXCEPT { return left.m_ptr - right.m_ptr; } //Comparison operators - friend bool operator== (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr == r.m_ptr; } - friend bool operator!= (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr != r.m_ptr; } - friend bool operator< (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr < r.m_ptr; } - friend bool operator<= (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr <= r.m_ptr; } - friend bool operator> (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr > r.m_ptr; } - friend bool operator>= (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr >= r.m_ptr; } }; -//! Iterator used to iterate through a vector -template -class vector_iterator - : public vector_const_iterator -{ - typedef vector_const_iterator base_t; - public: - explicit vector_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT - : base_t(ptr) - {} - - public: - 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() BOOST_CONTAINER_NOEXCEPT - : base_t() - {} - - //Pointer like operators - reference operator*() const BOOST_CONTAINER_NOEXCEPT - { return *this->m_ptr; } - - value_type* operator->() const BOOST_CONTAINER_NOEXCEPT - { return container_detail::to_raw_pointer(this->m_ptr); } - - reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT - { return this->m_ptr[off]; } - - //Increment / Decrement - vector_iterator& operator++() BOOST_CONTAINER_NOEXCEPT - { ++this->m_ptr; return *this; } - - vector_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT - { return vector_iterator(this->m_ptr++); } - - vector_iterator& operator--() BOOST_CONTAINER_NOEXCEPT - { --this->m_ptr; return *this; } - - vector_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT - { return vector_iterator(this->m_ptr--); } - - // Arithmetic - vector_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT - { this->m_ptr += off; return *this; } - - vector_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT - { this->m_ptr -= off; return *this; } - - friend vector_iterator operator+(vector_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT - { left.m_ptr += off; return left; } - - friend vector_iterator operator+(difference_type off, vector_iterator right) BOOST_CONTAINER_NOEXCEPT - { right.m_ptr += off; return right; } - - friend vector_iterator operator-(vector_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT - { left.m_ptr -= off; return left; } -}; - } //namespace container_detail { -template -const Pointer &vector_iterator_get_ptr(const container_detail::vector_const_iterator &it) BOOST_CONTAINER_NOEXCEPT +template +const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator &it) BOOST_CONTAINER_NOEXCEPT { return it.get_ptr(); } -template -Pointer &get_ptr(container_detail::vector_const_iterator &it) BOOST_CONTAINER_NOEXCEPT +template +Pointer &get_ptr(container_detail::vec_iterator &it) BOOST_CONTAINER_NOEXCEPT { return it.get_ptr(); } namespace container_detail { @@ -251,7 +199,7 @@ struct vector_get_ptr_pointer_to_non_const typedef typename pointer_traits_t ::template rebind_pointer::type return_type; - static return_type get_ptr(const const_pointer &ptr) + static return_type get_ptr(const const_pointer &ptr) BOOST_CONTAINER_NOEXCEPT { return boost::intrusive::pointer_traits::const_cast_from(ptr); } }; @@ -259,7 +207,7 @@ template struct vector_get_ptr_pointer_to_non_const { typedef const Pointer & return_type; - static return_type get_ptr(const Pointer &ptr) + static return_type get_ptr(const Pointer &ptr) BOOST_CONTAINER_NOEXCEPT { return ptr; } }; @@ -565,6 +513,7 @@ struct vector_alloc_holder::value > alloc_version; - boost::container::container_detail::vector_alloc_holder m_holder; - typedef container_detail::vector_alloc_holder base_t; - typedef allocator_traits allocator_traits_type; + boost::container::container_detail::vector_alloc_holder + m_holder; + typedef allocator_traits allocator_traits_type; template friend class vector; + + typedef typename ::boost::container::allocator_traits + ::pointer pointer_impl; + typedef container_detail::vec_iterator iterator_impl; + typedef container_detail::vec_iterator const_iterator_impl; + /// @endcond public: ////////////////////////////////////////////// @@ -611,8 +566,8 @@ class vector typedef BOOST_CONTAINER_IMPDEF(pointer) iterator; typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator; #else - typedef BOOST_CONTAINER_IMPDEF(container_detail::vector_iterator) iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::vector_const_iterator) const_iterator; + typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; + typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; #endif typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) reverse_iterator; typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) const_reverse_iterator; diff --git a/test/check_equal_containers.hpp b/test/check_equal_containers.hpp index 092846f..d2cd6b6 100644 --- a/test/check_equal_containers.hpp +++ b/test/check_equal_containers.hpp @@ -48,8 +48,6 @@ bool CheckEqualContainers(const MyBoostCont *boostcont, const MyStdCont *stdcont if(boostcont->size() != stdcont->size()) return false; - typedef typename MyBoostCont::value_type value_type; - typename MyBoostCont::const_iterator itboost(boostcont->begin()), itboostend(boostcont->end()); typename MyStdCont::const_iterator itstd(stdcont->begin()); typename MyStdCont::size_type dist = (typename MyStdCont::size_type)std::distance(itboost, itboostend); diff --git a/test/list_test.cpp b/test/list_test.cpp index fca017f..c7198e7 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -34,10 +34,10 @@ template class boost::container::list >::container_type::iterator >; -template class list_iterator - >::container_type::iterator>; +template class iterator + >::container_type::iterator, true >; +template class iterator + >::container_type::iterator, false>; } diff --git a/test/slist_test.cpp b/test/slist_test.cpp index 808d25c..785bcc2 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -31,15 +31,6 @@ template class boost::container::slist >; -namespace container_detail { - -template class slist_const_iterator - >::container_type::iterator >; -template class slist_iterator - >::container_type::iterator>; - -} - }} typedef slist MyList; diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp index 748886e..459aace 100644 --- a/test/stable_vector_test.cpp +++ b/test/stable_vector_test.cpp @@ -41,10 +41,10 @@ template class stable_vector; -template class iterator< int, const int &, const int *>; +template class iterator; +template class iterator; -} +} //namespace stable_vector_detail{ }} diff --git a/test/vector_test.cpp b/test/vector_test.cpp index 5ea8a05..3b34c92 100644 --- a/test/vector_test.cpp +++ b/test/vector_test.cpp @@ -43,8 +43,8 @@ namespace container_detail { #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER -template class vector_const_iterator; -template class vector_iterator; +template class vec_iterator; +template class vec_iterator; #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER From 027c92fad3b0992161697a088f79ca8351fcd7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 31 Aug 2013 21:49:26 +0000 Subject: [PATCH 12/26] Fixes #9064 [SVN r85537] --- doc/container.qbk | 5 +- include/boost/container/deque.hpp | 1 - include/boost/container/scoped_allocator.hpp | 111 ++++++++++++------- test/scoped_allocator_adaptor_test.cpp | 91 ++++++++++++--- 4 files changed, 147 insertions(+), 61 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 2c66420..26d418c 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -718,9 +718,10 @@ use [*Boost.Container]? There are several reasons for that: * Implemented [link container.main_features.scary_iterators SCARY iterators]. -* Fixed bugs [@https://svn.boost.org/trac/boost/ticket/8892 #8892], +* Fixed bugs [@https://svn.boost.org/trac/boost/ticket/8269 #8269], [@https://svn.boost.org/trac/boost/ticket/8473 #8473], - [@https://svn.boost.org/trac/boost/ticket/8269 #8269]. + [@https://svn.boost.org/trac/boost/ticket/8892 #8892], + [@https://svn.boost.org/trac/boost/ticket/9064 #9064]. [endsect] diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index 986b62f..e2dd4ee 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -736,7 +736,6 @@ class deque : protected deque_base } //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())); } diff --git a/include/boost/container/scoped_allocator.hpp b/include/boost/container/scoped_allocator.hpp index f9f2108..e594959 100644 --- a/include/boost/container/scoped_allocator.hpp +++ b/include/boost/container/scoped_allocator.hpp @@ -583,8 +583,10 @@ class scoped_allocator_adaptor_base }; typedef OuterAlloc outer_allocator_type; - typedef scoped_allocator_adaptor inner_allocator_type; - typedef allocator_traits inner_traits_type; + typedef scoped_allocator_adaptor inner_allocator_type; + typedef allocator_traits inner_traits_type; + typedef scoped_allocator_adaptor + scoped_allocator_type; typedef boost::integral_constant< bool, outer_traits_type::propagate_on_container_copy_assignment::value || @@ -635,7 +637,7 @@ class scoped_allocator_adaptor_base , m_inner(other.inner_allocator()) {} - protected: + public: struct internal_type_t{}; template @@ -670,6 +672,9 @@ class scoped_allocator_adaptor_base boost::container::swap_dispatch(this->m_inner, r.inner_allocator()); } + friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) + { l.swap(r); } + inner_allocator_type& inner_allocator() { return m_inner; } @@ -682,6 +687,15 @@ class scoped_allocator_adaptor_base const outer_allocator_type &outer_allocator() const { return static_cast(*this); } + scoped_allocator_type select_on_container_copy_construction() const + { + return scoped_allocator_type + (internal_type_t() + ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator()) + ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator()) + ); + } + private: inner_allocator_type m_inner; }; @@ -730,6 +744,11 @@ class scoped_allocator_adaptor_base inner_allocator_type; \ + typedef scoped_allocator_adaptor scoped_allocator_type; \ typedef allocator_traits inner_traits_type; \ typedef boost::integral_constant< \ bool, \ @@ -790,7 +809,7 @@ class scoped_allocator_adaptor_base \ @@ -824,6 +843,9 @@ class scoped_allocator_adaptor_basem_inner, r.inner_allocator()); \ } \ \ + friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) \ + { l.swap(r); } \ + \ inner_allocator_type& inner_allocator() \ { return m_inner; } \ \ @@ -836,6 +858,14 @@ class scoped_allocator_adaptor_base(*this); } \ \ + scoped_allocator_type select_on_container_copy_construction() const \ + { \ + return scoped_allocator_type \ + (internal_type_t() \ + ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator()) \ + ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator()) \ + ); \ + } \ private: \ inner_allocator_type m_inner; \ }; \ @@ -874,6 +904,7 @@ class scoped_allocator_adaptor_base typedef OuterAlloc outer_allocator_type; typedef allocator_traits outer_traits_type; typedef scoped_allocator_adaptor inner_allocator_type; + typedef inner_allocator_type scoped_allocator_type; typedef allocator_traits inner_traits_type; typedef typename outer_traits_type:: propagate_on_container_copy_assignment propagate_on_container_copy_assignment; @@ -922,7 +953,7 @@ class scoped_allocator_adaptor_base : outer_allocator_type(other.outer_allocator()) {} - protected: + public: struct internal_type_t{}; template @@ -948,6 +979,9 @@ class scoped_allocator_adaptor_base boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator()); } + friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) + { l.swap(r); } + inner_allocator_type& inner_allocator() { return static_cast(*this); } @@ -959,6 +993,17 @@ class scoped_allocator_adaptor_base const outer_allocator_type &outer_allocator() const { return static_cast(*this); } + + scoped_allocator_type select_on_container_copy_construction() const + { + return scoped_allocator_type + (internal_type_t() + ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator()) + //Don't use inner_traits_type::select_on_container_copy_construction(this->inner_allocator()) + //as inner_allocator() is equal to *this and that would trigger an infinite loop + , this->inner_allocator() + ); + } }; } //namespace container_detail { @@ -1040,7 +1085,7 @@ class scoped_allocator_adaptor , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q) #endif > base_type; - typedef typename base_type::internal_type_t internal_type_t; + typedef typename base_type::internal_type_t internal_type_t; /// @endcond typedef OuterAlloc outer_allocator_type; //! Type: For exposition only @@ -1164,48 +1209,37 @@ class scoped_allocator_adaptor {} scoped_allocator_adaptor &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor) other) - { - base_type::operator=(static_cast(other)); - return *this; - } + { return static_cast(base_type::operator=(static_cast(other))); } scoped_allocator_adaptor &operator=(BOOST_RV_REF(scoped_allocator_adaptor) other) - { - base_type::operator=(boost::move(static_cast(other))); - return *this; - } + { return static_cast(base_type::operator=(boost::move(static_cast(other)))); } + + #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED + //! Effects: swaps *this with r. + //! + void swap(scoped_allocator_adaptor &r); //! Effects: swaps *this with r. //! - void swap(scoped_allocator_adaptor &r) - { - base_type::swap(r); - } - - //! Effects: swaps *this with r. - //! - friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r) - { l.swap(r); } + friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r); //! Returns: //! `static_cast(*this)`. - outer_allocator_type & outer_allocator() - { return *this; } + outer_allocator_type & outer_allocator(); //! Returns: //! `static_cast(*this)`. - const outer_allocator_type &outer_allocator() const - { return *this; } + const outer_allocator_type &outer_allocator() const; //! Returns: //! *this if `sizeof...(InnerAllocs)` is zero; otherwise, inner. - inner_allocator_type& inner_allocator() - { return base_type::inner_allocator(); } + inner_allocator_type& inner_allocator(); //! Returns: //! *this if `sizeof...(InnerAllocs)` is zero; otherwise, inner. - inner_allocator_type const& inner_allocator() const - { return base_type::inner_allocator(); } + inner_allocator_type const& inner_allocator() const; + + #endif //BOOST_CONTAINER_DOXYGEN_INVOKED //! Returns: //! `allocator_traits::max_size(outer_allocator())`. @@ -1244,18 +1278,14 @@ class scoped_allocator_adaptor outer_traits_type::deallocate(this->outer_allocator(), p, n); } + #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED //! Returns: Allocator new scoped_allocator_adaptor object where each allocator //! A in the adaptor is initialized from the result of calling //! `allocator_traits::select_on_container_copy_construction()` on //! the corresponding allocator in *this. - scoped_allocator_adaptor select_on_container_copy_construction() const - { - return scoped_allocator_adaptor - (internal_type_t() - ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator()) - ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator()) - ); - } + scoped_allocator_adaptor select_on_container_copy_construction() const; + #endif //BOOST_CONTAINER_DOXYGEN_INVOKED + /// @cond base_type &base() { return *this; } @@ -1426,7 +1456,8 @@ class scoped_allocator_adaptor //template //void construct(pair* p, piecewise_construct_t, tuple x, tuple y); - private: + public: + //Internal function 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) diff --git a/test/scoped_allocator_adaptor_test.cpp b/test/scoped_allocator_adaptor_test.cpp index 61e8c7b..3464aa4 100644 --- a/test/scoped_allocator_adaptor_test.cpp +++ b/test/scoped_allocator_adaptor_test.cpp @@ -36,16 +36,20 @@ class test_allocator typedef T value_type; test_allocator() + : m_move_contructed(false), m_move_assigned(false) {} test_allocator(const test_allocator&) + : m_move_contructed(false), m_move_assigned(false) {} test_allocator(BOOST_RV_REF(test_allocator) ) + : m_move_contructed(true), m_move_assigned(false) {} template test_allocator(BOOST_RV_REF_BEG test_allocator BOOST_RV_REF_END) + : m_move_contructed(true), m_move_assigned(false) {} template @@ -53,10 +57,15 @@ class test_allocator {} test_allocator & operator=(BOOST_COPY_ASSIGN_REF(test_allocator)) - { return *this; } + { + return *this; + } test_allocator & operator=(BOOST_RV_REF(test_allocator)) - { return *this; } + { + m_move_assigned = true; + return *this; + } std::size_t max_size() const { return std::size_t(Id); } @@ -66,6 +75,9 @@ class test_allocator void deallocate(T*p, std::size_t) { delete []static_cast(static_cast(p)); } + + bool m_move_contructed; + bool m_move_assigned; }; template @@ -252,7 +264,6 @@ int main() typedef test_allocator, 1> InnerAlloc1; typedef test_allocator, 2> InnerAlloc2; typedef test_allocator, 11> Inner11IdAlloc1; - typedef test_allocator, 12> Inner12IdAlloc2; typedef test_allocator, 0, false> OuterAllocFalsePropagate; typedef test_allocator, 0, true> OuterAllocTruePropagate; @@ -277,11 +288,6 @@ int main() , InnerAlloc1 > ScopedScoped1Inner; - typedef scoped_allocator_adaptor - < scoped_allocator_adaptor - - , InnerAlloc1, InnerAlloc2 - > ScopedScoped2Inner; typedef scoped_allocator_adaptor< Rebound9OuterAlloc > Rebound9Scoped0Inner; typedef scoped_allocator_adaptor< Rebound9OuterAlloc , InnerAlloc1 > Rebound9Scoped1Inner; @@ -481,6 +487,64 @@ int main() Scoped1Inner s1i; } + //Copy constructor/assignment + { + Scoped0Inner s0i; + Scoped1Inner s1i; + Scoped2Inner s2i; + + Scoped0Inner s0i_b(s0i); + Scoped1Inner s1i_b(s1i); + Scoped2Inner s2i_b(s2i); + + if(!(s0i == s0i_b) || + !(s1i == s1i_b) || + !(s2i == s2i_b) + ){ + return 1; + } + + s0i_b = s0i; + s1i_b = s1i; + s2i_b = s2i; + + if(!(s0i == s0i_b) || + !(s1i == s1i_b) || + !(s2i == s2i_b) + ){ + return 1; + } + } + + //Copy/move constructor/assignment + { + Scoped0Inner s0i; + Scoped1Inner s1i; + Scoped2Inner s2i; + + Scoped0Inner s0i_b(::boost::move(s0i)); + Scoped1Inner s1i_b(::boost::move(s1i)); + Scoped2Inner s2i_b(::boost::move(s2i)); + + if(!(s0i_b.outer_allocator().m_move_contructed) || + !(s1i_b.outer_allocator().m_move_contructed) || + !(s2i_b.outer_allocator().m_move_contructed) + ){ + return 1; + } + + s0i_b = ::boost::move(s0i); + s1i_b = ::boost::move(s1i); + s2i_b = ::boost::move(s2i); + + if(!(s0i_b.outer_allocator().m_move_assigned) || + !(s1i_b.outer_allocator().m_move_assigned) || + !(s2i_b.outer_allocator().m_move_assigned) + ){ + return 1; + } + } + //inner_allocator() { Scoped0Inner s0i; @@ -880,7 +944,7 @@ int main() } ////////////////////////////////////////////////////////////////////////////////// - //Now test recursive OuterAllocator types (OuterAllocator is an scoped_allocator) + //Now test recursive OuterAllocator types (OuterAllocator is a scoped_allocator) ////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// @@ -1102,17 +1166,8 @@ int main() using boost::container::container_detail::pair; typedef test_allocator< pair< tagged_integer<0> , tagged_integer<0> >, 0> OuterPairAlloc; - typedef test_allocator< pair< tagged_integer<1> - , tagged_integer<1> >, 1> InnerPairAlloc1; - typedef test_allocator< pair< tagged_integer<2> - , tagged_integer<2> >, 2> InnerPairAlloc2; // typedef scoped_allocator_adaptor < OuterPairAlloc > ScopedPair0Inner; - typedef scoped_allocator_adaptor < OuterPairAlloc - , InnerPairAlloc1 > ScopedPair1Inner; - typedef scoped_allocator_adaptor < OuterPairAlloc - , InnerPairAlloc1 - , InnerPairAlloc2 > ScopedPair2Inner; ScopedPair0Inner s0i; //Check construction with 0 user arguments From 3e945acc9be0a1b6c53cf8921a8627625fa65123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 8 Sep 2013 18:58:21 +0000 Subject: [PATCH 13/26] Fixes #9092 [SVN r85612] --- doc/container.qbk | 1 + include/boost/container/detail/flat_tree.hpp | 146 +++++++------------ test/expand_bwd_test_template.hpp | 1 - test/flat_tree_test.cpp | 73 ---------- 4 files changed, 54 insertions(+), 167 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 26d418c..333bc09 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -722,6 +722,7 @@ use [*Boost.Container]? There are several reasons for that: [@https://svn.boost.org/trac/boost/ticket/8473 #8473], [@https://svn.boost.org/trac/boost/ticket/8892 #8892], [@https://svn.boost.org/trac/boost/ticket/9064 #9064]. + [@https://svn.boost.org/trac/boost/ticket/9092 #9092]. [endsect] diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 896f161..7f35b93 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -323,21 +323,21 @@ class flat_tree // insert/erase std::pair insert_unique(const value_type& val) { + std::pair ret; insert_commit_data data; - std::pair ret = this->priv_insert_unique_prepare(val, data); - if(ret.second){ - ret.first = this->priv_insert_commit(data, val); - } + ret.second = this->priv_insert_unique_prepare(val, data); + ret.first = ret.second ? this->priv_insert_commit(data, val) + : iterator(vector_iterator_get_ptr(data.position)); return ret; } std::pair insert_unique(BOOST_RV_REF(value_type) val) { + std::pair ret; insert_commit_data data; - std::pair ret = this->priv_insert_unique_prepare(val, data); - if(ret.second){ - ret.first = this->priv_insert_commit(data, boost::move(val)); - } + ret.second = this->priv_insert_unique_prepare(val, data); + ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val)) + : iterator(vector_iterator_get_ptr(data.position)); return ret; } @@ -357,22 +357,20 @@ class flat_tree iterator insert_unique(const_iterator pos, const value_type& val) { + std::pair ret; insert_commit_data data; - std::pair ret = this->priv_insert_unique_prepare(pos, val, data); - if(ret.second){ - ret.first = this->priv_insert_commit(data, val); - } - return ret.first; + return this->priv_insert_unique_prepare(pos, val, data) + ? this->priv_insert_commit(data, val) + : iterator(vector_iterator_get_ptr(data.position)); } - iterator insert_unique(const_iterator pos, BOOST_RV_REF(value_type) mval) + iterator insert_unique(const_iterator pos, BOOST_RV_REF(value_type) val) { + std::pair ret; insert_commit_data data; - std::pair ret = this->priv_insert_unique_prepare(pos, mval, data); - if(ret.second){ - ret.first = this->priv_insert_commit(data, boost::move(mval)); - } - return ret.first; + return this->priv_insert_unique_prepare(pos, val, data) + ? this->priv_insert_commit(data, boost::move(val)) + : iterator(vector_iterator_get_ptr(data.position)); } iterator insert_equal(const_iterator pos, const value_type& val) @@ -553,13 +551,7 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); value_destructor d(a, val); - insert_commit_data data; - std::pair ret = - this->priv_insert_unique_prepare(val, data); - if(ret.second){ - ret.first = this->priv_insert_commit(data, boost::move(val)); - } - return ret; + return this->insert_unique(::boost::move(val)); } template @@ -570,12 +562,7 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); value_destructor d(a, val); - insert_commit_data data; - std::pair ret = this->priv_insert_unique_prepare(hint, val, data); - if(ret.second){ - ret.first = this->priv_insert_commit(data, boost::move(val)); - } - return ret.first; + return this->insert_unique(hint, ::boost::move(val)); } template @@ -586,9 +573,7 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); value_destructor d(a, val); - iterator i = this->upper_bound(KeyOfValue()(val)); - i = this->m_data.m_vect.insert(i, boost::move(val)); - return i; + return this->insert_equal(::boost::move(val)); } template @@ -599,10 +584,7 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward(args)... ); value_destructor d(a, val); - insert_commit_data data; - this->priv_insert_equal_prepare(hint, val, data); - iterator i = this->priv_insert_commit(data, boost::move(val)); - return i; + return this->insert_equal(hint, ::boost::move(val)); } #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING @@ -618,12 +600,7 @@ class flat_tree stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ value_destructor d(a, val); \ - insert_commit_data data; \ - std::pair ret = this->priv_insert_unique_prepare(val, data); \ - if(ret.second){ \ - ret.first = this->priv_insert_commit(data, boost::move(val)); \ - } \ - return ret; \ + return this->insert_unique(::boost::move(val)); \ } \ \ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ @@ -635,13 +612,8 @@ class flat_tree stored_allocator_type &a = this->get_stored_allocator(); \ stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - value_destructor d(a, val); \ - insert_commit_data data; \ - std::pair ret = this->priv_insert_unique_prepare(hint, val, data); \ - if(ret.second){ \ - ret.first = this->priv_insert_commit(data, boost::move(val)); \ - } \ - return ret.first; \ + value_destructor d(a, val); \ + return this->insert_unique(hint, ::boost::move(val)); \ } \ \ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ @@ -653,9 +625,7 @@ class flat_tree stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ value_destructor d(a, val); \ - iterator i = this->upper_bound(KeyOfValue()(val)); \ - i = this->m_data.m_vect.insert(i, boost::move(val)); \ - return i; \ + return this->insert_equal(::boost::move(val)); \ } \ \ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ @@ -668,12 +638,8 @@ class flat_tree stored_allocator_traits::construct(a, &val \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ value_destructor d(a, val); \ - insert_commit_data data; \ - this->priv_insert_equal_prepare(hint, val, data); \ - iterator i = this->priv_insert_commit(data, boost::move(val)); \ - return i; \ + return this->insert_equal(hint, ::boost::move(val)); \ } \ - //! #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() @@ -798,21 +764,19 @@ class flat_tree } } - std::pair priv_insert_unique_prepare + bool priv_insert_unique_prepare (const_iterator b, const_iterator e, const value_type& val, insert_commit_data &commit_data) { const value_compare &value_comp = this->m_data; commit_data.position = this->priv_lower_bound(b, e, KeyOfValue()(val)); - return std::pair - ( iterator(vector_iterator_get_ptr(commit_data.position)) - , commit_data.position == e || value_comp(val, *commit_data.position)); + return commit_data.position == e || value_comp(val, *commit_data.position); } - std::pair priv_insert_unique_prepare + bool priv_insert_unique_prepare (const value_type& val, insert_commit_data &commit_data) - { return this->priv_insert_unique_prepare(this->begin(), this->end(), val, commit_data); } + { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), val, commit_data); } - std::pair priv_insert_unique_prepare + bool priv_insert_unique_prepare (const_iterator pos, const value_type& val, insert_commit_data &commit_data) { //N1780. Props to Howard Hinnant! @@ -827,37 +791,33 @@ class flat_tree //else // insert val before lower_bound(val) const value_compare &value_comp = this->m_data; - - if(pos == this->cend() || value_comp(val, *pos)){ - if(pos != this->cbegin() && !value_comp(val, pos[-1])){ - if(value_comp(pos[-1], val)){ - commit_data.position = pos; - return std::pair(iterator(vector_iterator_get_ptr(pos)), true); - } - else{ - return std::pair(iterator(vector_iterator_get_ptr(pos)), false); - } + const const_iterator cend_it = this->cend(); + if(pos == cend_it || value_comp(val, *pos)){ //Check if val should go before end + const const_iterator cbeg = this->cbegin(); + commit_data.position = pos; + if(pos == cbeg){ //If container is empty then insert it in the beginning + return true; + } + const_iterator prev(pos); + --prev; + if(value_comp(*prev, val)){ //If previous element was less, then it should go between prev and pos + return true; + } + else if(!value_comp(val, *prev)){ //If previous was equal then insertion should fail + commit_data.position = prev; + return false; + } + else{ //Previous was bigger so insertion hint was pointless, dispatch to hintless insertion + //but reduce the search between beg and prev as prev is bigger than val + return this->priv_insert_unique_prepare(cbeg, prev, val, commit_data); } - return this->priv_insert_unique_prepare(this->cbegin(), pos, val, commit_data); } - - // Works, but increases code complexity - //Next check - //else if (value_comp(*pos, val) && !value_comp(pos[1], val)){ - // if(value_comp(val, pos[1])){ - // commit_data.position = pos+1; - // return std::pair(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); + //in the remaining range [pos, end) + return this->priv_insert_unique_prepare(pos, cend_it, val, commit_data); } + //return priv_insert_unique_prepare(val, commit_data); } template diff --git a/test/expand_bwd_test_template.hpp b/test/expand_bwd_test_template.hpp index c1f26e1..7014466 100644 --- a/test/expand_bwd_test_template.hpp +++ b/test/expand_bwd_test_template.hpp @@ -183,7 +183,6 @@ 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}; diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp index 146285c..aac8a27 100644 --- a/test/flat_tree_test.cpp +++ b/test/flat_tree_test.cpp @@ -638,76 +638,3 @@ int main() #include -/* -#include -#include -#include -#include -#include - -struct Request -{ - Request() {}; - - //Move semantics... - Request(BOOST_RV_REF(Request) r) : rvals() //Move constructor - { - rvals.swap(r.rvals); - }; - - Request& operator=(BOOST_RV_REF(Request) r) //Move assignment - { - if (this != &r){ - rvals.swap(r.rvals); - } - return *this; - }; - - // Values I want to be moved, not copied. - boost::container::vector rvals; - - private: - // Mark this class movable but not copyable - BOOST_MOVABLE_BUT_NOT_COPYABLE(Request) -}; - -typedef boost::container::flat_map Requests; -//typedef boost::container::map Requests2; - -int -main() { - Requests req; - std::pair ret = req.insert( Requests::value_type( 7, Request() ) ); - std::cout << "Insert success for req: " << ret.second << std::endl; - - //Requests2 req2; - //std::pair ret2 = req2.insert( Requests2::value_type( 7, Request() ) ); - //std::cout << "Insert success for req2: " << ret2.second << std::endl; - - return 0; -} -*/ -/* -#include -#include -#include - -using namespace std; - -int main(int , char *[]) -{ - double d[] = {0, 0.2, 0.8, 1, 2, 3, 4}; - boost::container::flat_set set; - - set.insert(0); - set.insert(set.end(), 1); - set.insert(set.end(), 3); - set.insert(boost::container::ordered_unique_range_t(), d, d + sizeof(d)/sizeof(*d)); - boost::container::flat_set::iterator it(set.begin()); - boost::container::flat_set::iterator const itend(set.end()); - while(it != itend) - cout << *it++ << endl; - - return 0; -} -*/ \ No newline at end of file From 5a4073434b9d54f639db41a38a6da61b5b724128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 9 Sep 2013 19:26:50 +0000 Subject: [PATCH 14/26] Removed SGI copyright as after rewrites it is no longer applicable. [SVN r85625] --- include/boost/container/deque.hpp | 22 ---------------------- include/boost/container/string.hpp | 22 ---------------------- 2 files changed, 44 deletions(-) diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index e2dd4ee..0fa5196 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -7,28 +7,6 @@ // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// -// Copyright (c) 1996,1997 -// Silicon Graphics Computer Systems, Inc. -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. Silicon Graphics makes no -// representations about the suitability of this software for any -// purpose. It is provided "as is" without express or implied warranty. -// -// -// Copyright (c) 1994 -// Hewlett-Packard Company -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. Hewlett-Packard Company makes no -// representations about the suitability of this software for any -// purpose. It is provided "as is" without express or implied warranty. #ifndef BOOST_CONTAINER_DEQUE_HPP #define BOOST_CONTAINER_DEQUE_HPP diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index e97f789..197bb85 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -7,28 +7,6 @@ // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// -// Copyright (c) 1996,1997 -// Silicon Graphics Computer Systems, Inc. -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. Silicon Graphics makes no -// representations about the suitability of this software for any -// purpose. It is provided "as is" without express or implied warranty. -// -// -// Copyright (c) 1994 -// Hewlett-Packard Company -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. Hewlett-Packard Company makes no -// representations about the suitability of this software for any -// purpose. It is provided "as is" without express or implied warranty. #ifndef BOOST_CONTAINER_STRING_HPP #define BOOST_CONTAINER_STRING_HPP From 7d69794f7ea64369a74ef96d66531c212e616277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 9 Sep 2013 19:36:10 +0000 Subject: [PATCH 15/26] Removed SGI copyright as after rewrites it is no longer applicable. [SVN r85627] --- doc/container.qbk | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 333bc09..ef55777 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -688,9 +688,8 @@ use [*Boost.Container]? There are several reasons for that: [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, David Musser, + which enhanced the original HP STL code. Code was rewritten for + [*Boost.Interprocess] and moved to [*Boost.Intrusive]. 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] From ed57e6e619f63dcc7eba37066f3cc925d1baff43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 12 Sep 2013 21:50:38 +0000 Subject: [PATCH 16/26] Fixes #9108 [SVN r85658] --- doc/container.qbk | 5 +++-- include/boost/container/vector.hpp | 9 ++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index ef55777..66c6c3d 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -720,8 +720,9 @@ use [*Boost.Container]? There are several reasons for that: * Fixed bugs [@https://svn.boost.org/trac/boost/ticket/8269 #8269], [@https://svn.boost.org/trac/boost/ticket/8473 #8473], [@https://svn.boost.org/trac/boost/ticket/8892 #8892], - [@https://svn.boost.org/trac/boost/ticket/9064 #9064]. - [@https://svn.boost.org/trac/boost/ticket/9092 #9092]. + [@https://svn.boost.org/trac/boost/ticket/9064 #9064], + [@https://svn.boost.org/trac/boost/ticket/9092 #9092], + [@https://svn.boost.org/trac/boost/ticket/9108 #9108]. [endsect] diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index db41b60..848364f 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -1634,7 +1634,11 @@ class vector const size_type sz = m_holder.m_size; ::boost::container::uninitialized_move_alloc_n_source ( this->m_holder.alloc(), raw_beg, sz, container_detail::to_raw_pointer(p) ); + if(this->m_holder.capacity()){ + if(!value_traits::trivial_dctr_after_move) boost::container::destroy_alloc_n(this->m_holder.alloc(), raw_beg, sz); + this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity()); + } this->m_holder.start(p); this->m_holder.capacity(new_cap); } @@ -1677,7 +1681,6 @@ class vector } //New buffer else{ - //Backwards (and possibly forward) expansion #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_alloc; #endif @@ -1685,7 +1688,11 @@ class vector const size_type sz = m_holder.m_size; ::boost::container::uninitialized_move_alloc_n_source ( this->m_holder.alloc(), raw_beg, sz, container_detail::to_raw_pointer(ret.first) ); + if(this->m_holder.capacity()){ + if(!value_traits::trivial_dctr_after_move) boost::container::destroy_alloc_n(this->m_holder.alloc(), raw_beg, sz); + this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity()); + } this->m_holder.start(ret.first); this->m_holder.capacity(real_cap); } From a7b88d804c824566bcf18d779ee4eafd8c87c082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 12 Sep 2013 22:00:51 +0000 Subject: [PATCH 17/26] Fixes #9009 [SVN r85660] --- doc/container.qbk | 1 + include/boost/container/deque.hpp | 2 +- include/boost/container/flat_set.hpp | 4 ++-- include/boost/container/list.hpp | 2 +- include/boost/container/set.hpp | 4 ++-- include/boost/container/slist.hpp | 4 ++-- include/boost/container/stable_vector.hpp | 2 +- include/boost/container/vector.hpp | 6 +++--- 8 files changed, 13 insertions(+), 12 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 66c6c3d..1238ce8 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -720,6 +720,7 @@ use [*Boost.Container]? There are several reasons for that: * Fixed bugs [@https://svn.boost.org/trac/boost/ticket/8269 #8269], [@https://svn.boost.org/trac/boost/ticket/8473 #8473], [@https://svn.boost.org/trac/boost/ticket/8892 #8892], + [@https://svn.boost.org/trac/boost/ticket/9009 #9009], [@https://svn.boost.org/trac/boost/ticket/9064 #9064], [@https://svn.boost.org/trac/boost/ticket/9092 #9092], [@https://svn.boost.org/trac/boost/ticket/9108 #9108]. diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index 0fa5196..85649ff 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -1301,7 +1301,7 @@ class deque : protected deque_base //! Linear time otherwise. iterator insert(const_iterator position, T &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator) #endif //! Requires: pos must be a valid iterator of *this. diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index eed7dda..5501ed5 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -512,7 +512,7 @@ class flat_set //! Note: If an element is inserted it might invalidate elements. iterator insert(const_iterator position, value_type &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator) #endif //! Requires: first, last are not iterators into *this. @@ -1189,7 +1189,7 @@ class flat_multiset //! Note: If an element is inserted it might invalidate elements. iterator insert(const_iterator position, value_type &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator) #endif //! Requires: first, last are not iterators into *this. diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index e613f4a..2a785c2 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -777,7 +777,7 @@ class list //! 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) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator) #endif //! Requires: p must be a valid iterator of *this. diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 7808859..508ddc3 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -457,7 +457,7 @@ class set //! Complexity: Logarithmic. iterator insert(const_iterator position, value_type &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator) #endif //! Requires: first, last are not iterators into *this. @@ -1077,7 +1077,7 @@ class multiset //! is inserted right before p. iterator insert(const_iterator position, value_type &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator) #endif //! Requires: first, last are not iterators into *this. diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index e0aa95f..6accfcc 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -753,7 +753,7 @@ class slist //! previous values. iterator insert_after(const_iterator prev_pos, T &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_after, T, iterator, priv_insert_after, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_after, T, iterator, priv_insert_after, const_iterator, const_iterator) #endif //! Requires: prev_pos must be a valid iterator of *this. @@ -1266,7 +1266,7 @@ class slist //! Complexity: Linear to the elements before p. iterator insert(const_iterator prev_pos, T &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator) #endif //! Requires: p must be a valid iterator of *this. diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index c5353f3..1e6f190 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -1306,7 +1306,7 @@ class stable_vector //! Linear time otherwise. iterator insert(const_iterator position, T &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator) #endif //! Requires: pos must be a valid iterator of *this. diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 848364f..25f18c1 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -1347,7 +1347,7 @@ class vector //! Linear time otherwise. iterator insert(const_iterator position, T &&x); #else - BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator) + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator) #endif //! Requires: p must be a valid iterator of *this. @@ -1636,7 +1636,7 @@ class vector ( this->m_holder.alloc(), raw_beg, sz, container_detail::to_raw_pointer(p) ); if(this->m_holder.capacity()){ if(!value_traits::trivial_dctr_after_move) - boost::container::destroy_alloc_n(this->m_holder.alloc(), raw_beg, sz); + boost::container::destroy_alloc_n(this->m_holder.alloc(), raw_beg, sz); this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity()); } this->m_holder.start(p); @@ -1690,7 +1690,7 @@ class vector ( this->m_holder.alloc(), raw_beg, sz, container_detail::to_raw_pointer(ret.first) ); if(this->m_holder.capacity()){ if(!value_traits::trivial_dctr_after_move) - boost::container::destroy_alloc_n(this->m_holder.alloc(), raw_beg, sz); + boost::container::destroy_alloc_n(this->m_holder.alloc(), raw_beg, sz); this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity()); } this->m_holder.start(ret.first); From 1e4be891d02d8b4c1384a8f2ba1ca6a1bd0ddf33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 15 Sep 2013 19:47:36 +0000 Subject: [PATCH 18/26] Remove unused header. [SVN r85687] --- test/util.hpp | 113 -------------------------------------------------- 1 file changed, 113 deletions(-) delete mode 100644 test/util.hpp diff --git a/test/util.hpp b/test/util.hpp deleted file mode 100644 index 9bfe1af..0000000 --- a/test/util.hpp +++ /dev/null @@ -1,113 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2004-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. -// -////////////////////////////////////////////////////////////////////////////// -// 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 From eb4b320fedb5535ab36be5956892e111dab12d8c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 25 Sep 2013 21:17:34 +0000 Subject: [PATCH 19/26] Container: Fix two pragma guards. Fix typo in the MSC_VER macro check [SVN r85923] --- include/boost/container/scoped_allocator.hpp | 2 +- include/boost/container/scoped_allocator_fwd.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/container/scoped_allocator.hpp b/include/boost/container/scoped_allocator.hpp index e594959..d16ac37 100644 --- a/include/boost/container/scoped_allocator.hpp +++ b/include/boost/container/scoped_allocator.hpp @@ -17,7 +17,7 @@ #ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP #define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP -#if (defined MSC_VER) && (_MSC_VER >= 1200) +#if defined (_MSC_VER) # pragma once #endif diff --git a/include/boost/container/scoped_allocator_fwd.hpp b/include/boost/container/scoped_allocator_fwd.hpp index ef24799..4c066b0 100644 --- a/include/boost/container/scoped_allocator_fwd.hpp +++ b/include/boost/container/scoped_allocator_fwd.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP #define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP -#if (defined MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif From 59b2793df795516e9486165cd45cf78e04100469 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 26 Sep 2013 13:02:51 +0000 Subject: [PATCH 20/26] Remove obsolete MSVC check from pragma guard git grep -h -B1 "^#\s*pragma once" | grep -v pragma | sort | uniq is now clean. [SVN r85952] --- bench/detail/varray.hpp | 2 +- bench/varray.hpp | 2 +- include/boost/container/allocator_traits.hpp | 2 +- include/boost/container/container_fwd.hpp | 2 +- include/boost/container/deque.hpp | 2 +- include/boost/container/detail/adaptive_node_pool_impl.hpp | 2 +- include/boost/container/detail/advanced_insert_int.hpp | 2 +- include/boost/container/detail/algorithms.hpp | 2 +- include/boost/container/detail/allocation_type.hpp | 2 +- include/boost/container/detail/allocator_version_traits.hpp | 2 +- include/boost/container/detail/destroyers.hpp | 2 +- include/boost/container/detail/flat_tree.hpp | 2 +- include/boost/container/detail/iterators.hpp | 2 +- include/boost/container/detail/memory_util.hpp | 2 +- include/boost/container/detail/mpl.hpp | 2 +- include/boost/container/detail/node_alloc_holder.hpp | 2 +- include/boost/container/detail/node_pool_impl.hpp | 2 +- include/boost/container/detail/pair.hpp | 2 +- include/boost/container/detail/pool_common.hpp | 2 +- include/boost/container/detail/preprocessor.hpp | 2 +- include/boost/container/detail/transform_iterator.hpp | 2 +- include/boost/container/detail/type_traits.hpp | 2 +- include/boost/container/detail/value_init.hpp | 2 +- include/boost/container/detail/variadic_templates_tools.hpp | 2 +- include/boost/container/flat_map.hpp | 2 +- include/boost/container/flat_set.hpp | 2 +- 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/static_vector.hpp | 2 +- include/boost/container/throw_exception.hpp | 2 +- include/boost/container/vector.hpp | 2 +- test/dummy_test_allocator.hpp | 2 +- test/expand_bwd_test_allocator.hpp | 2 +- test/heap_allocator_v1.hpp | 2 +- 37 files changed, 37 insertions(+), 37 deletions(-) diff --git a/bench/detail/varray.hpp b/bench/detail/varray.hpp index e28eb47..e0729f0 100644 --- a/bench/detail/varray.hpp +++ b/bench/detail/varray.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_CONTAINER_DETAIL_VARRAY_HPP #define BOOST_CONTAINER_DETAIL_VARRAY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if (defined _MSC_VER) # pragma once #endif diff --git a/bench/varray.hpp b/bench/varray.hpp index 8e911cb..1e15d82 100644 --- a/bench/varray.hpp +++ b/bench/varray.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_CONTAINER_VARRAY_HPP #define BOOST_CONTAINER_VARRAY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if (defined _MSC_VER) # pragma once #endif diff --git a/include/boost/container/allocator_traits.hpp b/include/boost/container/allocator_traits.hpp index 64e4352..19c35a8 100644 --- a/include/boost/container/allocator_traits.hpp +++ b/include/boost/container/allocator_traits.hpp @@ -17,7 +17,7 @@ #ifndef BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP #define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/container_fwd.hpp b/include/boost/container/container_fwd.hpp index bdefd81..3b47b2f 100644 --- a/include/boost/container/container_fwd.hpp +++ b/include/boost/container/container_fwd.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP #define BOOST_CONTAINER_CONTAINER_FWD_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index 85649ff..98b66ee 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_DEQUE_HPP #define BOOST_CONTAINER_DEQUE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/adaptive_node_pool_impl.hpp b/include/boost/container/detail/adaptive_node_pool_impl.hpp index 8b673cf..4578ea8 100644 --- a/include/boost/container/detail/adaptive_node_pool_impl.hpp +++ b/include/boost/container/detail/adaptive_node_pool_impl.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP #define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/advanced_insert_int.hpp b/include/boost/container/detail/advanced_insert_int.hpp index 86e2628..47539b3 100644 --- a/include/boost/container/detail/advanced_insert_int.hpp +++ b/include/boost/container/detail/advanced_insert_int.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP #define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/algorithms.hpp b/include/boost/container/detail/algorithms.hpp index 824e44b..072cf9c 100644 --- a/include/boost/container/detail/algorithms.hpp +++ b/include/boost/container/detail/algorithms.hpp @@ -13,7 +13,7 @@ #ifndef BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP #define BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/allocation_type.hpp b/include/boost/container/detail/allocation_type.hpp index 1ebf20e..59ae922 100644 --- a/include/boost/container/detail/allocation_type.hpp +++ b/include/boost/container/detail/allocation_type.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_ALLOCATION_TYPE_HPP #define BOOST_CONTAINER_ALLOCATION_TYPE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/allocator_version_traits.hpp b/include/boost/container/detail/allocator_version_traits.hpp index 4cef676..e051707 100644 --- a/include/boost/container/detail/allocator_version_traits.hpp +++ b/include/boost/container/detail/allocator_version_traits.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP #define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/destroyers.hpp b/include/boost/container/detail/destroyers.hpp index f9bfd86..6865466 100644 --- a/include/boost/container/detail/destroyers.hpp +++ b/include/boost/container/detail/destroyers.hpp @@ -13,7 +13,7 @@ #ifndef BOOST_CONTAINER_DESTROYERS_HPP #define BOOST_CONTAINER_DESTROYERS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 7f35b93..0aad21f 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_FLAT_TREE_HPP #define BOOST_CONTAINER_FLAT_TREE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/iterators.hpp b/include/boost/container/detail/iterators.hpp index 03ac6c9..500e6b9 100644 --- a/include/boost/container/detail/iterators.hpp +++ b/include/boost/container/detail/iterators.hpp @@ -14,7 +14,7 @@ #ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP #define BOOST_CONTAINER_DETAIL_ITERATORS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/memory_util.hpp b/include/boost/container/detail/memory_util.hpp index ac9a899..ed89954 100644 --- a/include/boost/container/detail/memory_util.hpp +++ b/include/boost/container/detail/memory_util.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP #define BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/mpl.hpp b/include/boost/container/detail/mpl.hpp index 74a1ce0..08f3eae 100644 --- a/include/boost/container/detail/mpl.hpp +++ b/include/boost/container/detail/mpl.hpp @@ -13,7 +13,7 @@ #ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP #define BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index 4a5052a..4ab26c9 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_ #define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_ -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/node_pool_impl.hpp b/include/boost/container/detail/node_pool_impl.hpp index 2103898..0c5c744 100644 --- a/include/boost/container/detail/node_pool_impl.hpp +++ b/include/boost/container/detail/node_pool_impl.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP #define BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/pair.hpp b/include/boost/container/detail/pair.hpp index 79753a8..bfe7978 100644 --- a/include/boost/container/detail/pair.hpp +++ b/include/boost/container/detail/pair.hpp @@ -13,7 +13,7 @@ #ifndef BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP #define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/pool_common.hpp b/include/boost/container/detail/pool_common.hpp index 983d141..6ab2d43 100644 --- a/include/boost/container/detail/pool_common.hpp +++ b/include/boost/container/detail/pool_common.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP #define BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/preprocessor.hpp b/include/boost/container/detail/preprocessor.hpp index 4e175a8..41d1f55 100644 --- a/include/boost/container/detail/preprocessor.hpp +++ b/include/boost/container/detail/preprocessor.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP #define BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/transform_iterator.hpp b/include/boost/container/detail/transform_iterator.hpp index 98f5c04..c40ecc6 100644 --- a/include/boost/container/detail/transform_iterator.hpp +++ b/include/boost/container/detail/transform_iterator.hpp @@ -14,7 +14,7 @@ #ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP #define BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/type_traits.hpp b/include/boost/container/detail/type_traits.hpp index 5020ee9..8dbd182 100644 --- a/include/boost/container/detail/type_traits.hpp +++ b/include/boost/container/detail/type_traits.hpp @@ -15,7 +15,7 @@ #ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP #define BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/value_init.hpp b/include/boost/container/detail/value_init.hpp index ec1a99c..afe5b15 100644 --- a/include/boost/container/detail/value_init.hpp +++ b/include/boost/container/detail/value_init.hpp @@ -13,7 +13,7 @@ #ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP #define BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/detail/variadic_templates_tools.hpp b/include/boost/container/detail/variadic_templates_tools.hpp index d903dfa..cce7fed 100644 --- a/include/boost/container/detail/variadic_templates_tools.hpp +++ b/include/boost/container/detail/variadic_templates_tools.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP #define BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index da992aa..9da14c9 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_FLAT_MAP_HPP #define BOOST_CONTAINER_FLAT_MAP_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 5501ed5..77711cc 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_FLAT_SET_HPP #define BOOST_CONTAINER_FLAT_SET_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 2a785c2..2eff808 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_CONTAINER_LIST_HPP #define BOOST_CONTAINER_LIST_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index e6ca865..e0b5581 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_MAP_HPP #define BOOST_CONTAINER_MAP_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 508ddc3..d215df4 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_SET_HPP #define BOOST_CONTAINER_SET_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index 6accfcc..37a3b52 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_SLIST_HPP #define BOOST_CONTAINER_SLIST_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 1e6f190..c64a339 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -19,7 +19,7 @@ #ifndef BOOST_CONTAINER_STABLE_VECTOR_HPP #define BOOST_CONTAINER_STABLE_VECTOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/static_vector.hpp b/include/boost/container/static_vector.hpp index 4a8cce4..17aafc2 100644 --- a/include/boost/container/static_vector.hpp +++ b/include/boost/container/static_vector.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_CONTAINER_STATIC_VECTOR_HPP #define BOOST_CONTAINER_STATIC_VECTOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/throw_exception.hpp b/include/boost/container/throw_exception.hpp index e22d104..7c821c0 100644 --- a/include/boost/container/throw_exception.hpp +++ b/include/boost/container/throw_exception.hpp @@ -14,7 +14,7 @@ #include #include -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 25f18c1..97a1ceb 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP #define BOOST_CONTAINER_CONTAINER_VECTOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/test/dummy_test_allocator.hpp b/test/dummy_test_allocator.hpp index afdd042..29feec3 100644 --- a/test/dummy_test_allocator.hpp +++ b/test/dummy_test_allocator.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP #define BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if (defined _MSC_VER) # pragma once #endif diff --git a/test/expand_bwd_test_allocator.hpp b/test/expand_bwd_test_allocator.hpp index 81bf016..1bd375a 100644 --- a/test/expand_bwd_test_allocator.hpp +++ b/test/expand_bwd_test_allocator.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP #define BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if (defined _MSC_VER) # pragma once #endif diff --git a/test/heap_allocator_v1.hpp b/test/heap_allocator_v1.hpp index 43603f7..b6661d1 100644 --- a/test/heap_allocator_v1.hpp +++ b/test/heap_allocator_v1.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_CONTAINER_HEAP_ALLOCATOR_V1_HPP #define BOOST_CONTAINER_HEAP_ALLOCATOR_V1_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if (defined _MSC_VER) # pragma once #endif From 14f092ab00def8e692b81d57d0466a617a6f6130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 26 Sep 2013 18:05:25 +0000 Subject: [PATCH 21/26] Default initialization for vector-like containers Complexity guarantees for associative container constructors and ordered input ranges Added benchmark for associative containers Fixes #9166 [SVN r85964] --- bench/Jamfile.v2 | 2 +- bench/bench_set.cpp | 348 ++++++++++++++++++ bench/bench_static_vector.cpp | 1 - bench/detail/varray.hpp | 4 +- bench/varray.hpp | 4 +- doc/container.qbk | 46 +++ include/boost/container/allocator_traits.hpp | 5 + include/boost/container/container_fwd.hpp | 17 +- include/boost/container/deque.hpp | 47 ++- .../container/detail/advanced_insert_int.hpp | 30 +- include/boost/container/detail/algorithms.hpp | 12 +- .../detail/allocator_version_traits.hpp | 8 +- .../boost/container/detail/config_begin.hpp | 1 + include/boost/container/detail/destroyers.hpp | 11 + include/boost/container/detail/flat_tree.hpp | 98 ++--- include/boost/container/detail/iterators.hpp | 158 ++++++-- .../detail/multiallocation_chain.hpp | 6 +- .../container/detail/node_alloc_holder.hpp | 32 +- include/boost/container/detail/tree.hpp | 206 ++++++----- include/boost/container/detail/utilities.hpp | 39 +- include/boost/container/flat_map.hpp | 6 +- include/boost/container/flat_set.hpp | 2 +- include/boost/container/list.hpp | 6 +- include/boost/container/map.hpp | 6 +- include/boost/container/set.hpp | 6 +- include/boost/container/slist.hpp | 6 +- include/boost/container/stable_vector.hpp | 50 ++- include/boost/container/static_vector.hpp | 39 +- include/boost/container/string.hpp | 2 +- include/boost/container/vector.hpp | 75 +++- proj/vc7ide/bench_set.vcproj | 134 +++++++ proj/vc7ide/container.sln | 18 +- proj/vc7ide/container.vcproj | 3 + test/allocator_traits_test.cpp | 51 ++- test/deque_test.cpp | 4 + test/stable_vector_test.cpp | 35 ++ test/static_vector_test.cpp | 50 +++ test/vector_test.cpp | 4 + test/vector_test.hpp | 120 +++++- 39 files changed, 1450 insertions(+), 242 deletions(-) create mode 100644 bench/bench_set.cpp create mode 100644 proj/vc7ide/bench_set.vcproj diff --git a/bench/Jamfile.v2 b/bench/Jamfile.v2 index 25add18..cc1e715 100644 --- a/bench/Jamfile.v2 +++ b/bench/Jamfile.v2 @@ -21,7 +21,7 @@ rule test_all for local fileb in [ glob *.cpp ] { - all_rules += [ run $(fileb) /boost/timer//boost_timer /boost/system//boost_system /boost/thread//boost_thread + all_rules += [ run $(fileb) /boost/timer//boost_timer : # additional args : # test-files : # requirements diff --git a/bench/bench_set.cpp b/bench/bench_set.cpp new file mode 100644 index 0000000..662d11b --- /dev/null +++ b/bench/bench_set.cpp @@ -0,0 +1,348 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include "boost/container/set.hpp" +#include "boost/container/flat_set.hpp" +#include +#include +#include +#include +#include +#include + +using boost::timer::cpu_timer; +using boost::timer::cpu_times; +using boost::timer::nanosecond_type; + +#ifdef NDEBUG +static const std::size_t N = 5000; +#else +static const std::size_t N = 500; +#endif + +void compare_times(cpu_times time_numerator, cpu_times time_denominator){ + std::cout << "----------------------------------------------" << '\n'; + std::cout << " wall = " << ((double)time_numerator.wall/(double)time_denominator.wall) << std::endl; + std::cout << "----------------------------------------------" << '\n' << std::endl; +} + +std::vector sorted_unique_range; +std::vector sorted_range; +std::vector random_unique_range; +std::vector random_range; + +void fill_ranges() +{ + sorted_unique_range.resize(N); + sorted_range.resize(N); + random_unique_range.resize(N); + random_range.resize(N); + std::srand (0); + //random_range + std::generate(random_unique_range.begin(), random_unique_range.end(), std::rand); + random_unique_range.erase(std::unique(random_unique_range.begin(), random_unique_range.end()), random_unique_range.end()); + //random_range + random_range = random_unique_range; + random_range.insert(random_range.end(), random_unique_range.begin(), random_unique_range.end()); + //sorted_unique_range + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + sorted_unique_range[i] = static_cast(i); + } + //sorted_range + sorted_range = sorted_unique_range; + sorted_range.insert(sorted_range.end(), sorted_unique_range.begin(), sorted_unique_range.end()); + std::sort(sorted_range.begin(), sorted_range.end()); +} + +template +cpu_times construct_time() +{ + cpu_timer sur_timer, sr_timer, rur_timer, rr_timer, copy_timer, assign_timer, destroy_timer; + //sur_timer.stop();sr_timer.stop();rur_timer.stop();rr_timer.stop();destroy_timer.stop(); + + cpu_timer total_time; + total_time.resume(); + + for(std::size_t i = 0; i != N; ++i){ + { + sur_timer.resume(); + T t(sorted_unique_range.begin(), sorted_unique_range.end()); + sur_timer.stop(); + } + { + sr_timer.resume(); + T t(sorted_range.begin(), sorted_range.end()); + sr_timer.stop(); + copy_timer.resume(); + T taux(t); + copy_timer.stop(); + assign_timer.resume(); + t = taux;; + assign_timer.stop(); + } + { + rur_timer.resume(); + T t(random_unique_range.begin(), random_unique_range.end()); + rur_timer.stop(); + } + { + rr_timer.resume(); + T t(random_range.begin(), random_range.end()); + rr_timer.stop(); + destroy_timer.resume(); + } + destroy_timer.stop(); + } + total_time.stop(); + + std::cout << " Construct sorted_unique_range " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Construct sorted_range " << boost::timer::format(sr_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Copy sorted range " << boost::timer::format(copy_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Assign sorted range " << boost::timer::format(assign_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Construct random_unique_range " << boost::timer::format(rur_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Construct random_range " << boost::timer::format(rr_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Destroy " << boost::timer::format(destroy_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws wall\n") << std::endl; + return total_time.elapsed(); +} + +template +cpu_times insert_time() +{ + cpu_timer sur_timer,sr_timer,rur_timer,rr_timer,destroy_timer; + sur_timer.stop();sr_timer.stop();rur_timer.stop();rr_timer.stop(); + + cpu_timer total_time; + total_time.resume(); + + for(std::size_t i = 0; i != N; ++i){ + { + sur_timer.resume(); + T t; + t.insert(sorted_unique_range.begin(), sorted_unique_range.end()); + sur_timer.stop(); + } + { + sr_timer.resume(); + T t; + t.insert(sorted_range.begin(), sorted_range.end()); + sr_timer.stop(); + } + { + rur_timer.resume(); + T t; + t.insert(random_unique_range.begin(), random_unique_range.end()); + rur_timer.stop(); + } + { + rr_timer.resume(); + T t; + t.insert(random_range.begin(), random_range.end()); + rr_timer.stop(); + } + } + total_time.stop(); + + std::cout << " Insert sorted_unique_range " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Insert sorted_range " << boost::timer::format(sr_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Insert random_unique_range " << boost::timer::format(rur_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Insert random_range " << boost::timer::format(rr_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws wall\n") << std::endl; + return total_time.elapsed(); +} + +template +cpu_times search_time() +{ + cpu_timer find_timer, lower_timer, upper_timer, equal_range_timer, count_timer; + + T t(sorted_unique_range.begin(), sorted_unique_range.end()); + + cpu_timer total_time; + total_time.resume(); + + for(std::size_t i = 0; i != N; ++i){ + //Find + { + std::size_t found = 0; + find_timer.resume(); + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + found += static_cast(t.end() != t.find(sorted_unique_range[i])); + } + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + found += static_cast(t.end() != t.find(sorted_unique_range[i])); + } + find_timer.stop(); + if(found/2 != t.size()){ + std::cout << "ERROR! all elements not found" << std::endl; + } + } + //Lower + { + std::size_t found = 0; + lower_timer.resume(); + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + found += static_cast(t.end() != t.lower_bound(sorted_unique_range[i])); + } + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + found += static_cast(t.end() != t.lower_bound(sorted_unique_range[i])); + } + lower_timer.stop(); + if(found/2 != t.size()){ + std::cout << "ERROR! all elements not found" << std::endl; + } + } + //Upper + { + std::size_t found = 0; + upper_timer.resume(); + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + found += static_cast(t.end() != t.upper_bound(sorted_unique_range[i])); + } + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + found += static_cast(t.end() != t.upper_bound(sorted_unique_range[i])); + } + upper_timer.stop(); + if(found/2 != (t.size()-1)){ + std::cout << "ERROR! all elements not found" << std::endl; + } + } + //Equal + { + std::size_t found = 0; + std::pair ret; + equal_range_timer.resume(); + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + ret = t.equal_range(sorted_unique_range[i]); + found += static_cast(ret.first != ret.second); + } + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + ret = t.equal_range(sorted_unique_range[i]); + found += static_cast(ret.first != ret.second); + } + equal_range_timer.stop(); + if(found/2 != t.size()){ + std::cout << "ERROR! all elements not found" << std::endl; + } + } + //Count + { + std::size_t found = 0; + std::pair ret; + count_timer.resume(); + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + found += static_cast(t.count(sorted_unique_range[i])); + } + for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){ + found += static_cast(t.count(sorted_unique_range[i])); + } + count_timer.stop(); + if(found/2 != t.size()){ + std::cout << "ERROR! all elements not found" << std::endl; + } + } + } + total_time.stop(); + + std::cout << " Find " << boost::timer::format(find_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Lower Bound " << boost::timer::format(lower_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Upper Bound " << boost::timer::format(upper_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Equal Range " << boost::timer::format(equal_range_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Count " << boost::timer::format(count_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws wall\n") << std::endl; + return total_time.elapsed(); +} + +template +void extensions_time() +{ + cpu_timer sur_timer,sur_opt_timer; + sur_timer.stop();sur_opt_timer.stop(); + + for(std::size_t i = 0; i != N; ++i){ + { + sur_timer.resume(); + T t(sorted_unique_range.begin(), sorted_unique_range.end()); + sur_timer.stop(); + } + { + sur_opt_timer.resume(); + T t(boost::container::ordered_unique_range, sorted_unique_range.begin(), sorted_unique_range.end()); + sur_opt_timer.stop(); + } + + } + std::cout << " Construct sorted_unique_range " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << " Construct sorted_unique_range (extension) " << boost::timer::format(sur_opt_timer.elapsed(), boost::timer::default_places, "%ws wall\n"); + std::cout << "Total time (Extension/Standard):\n"; + compare_times(sur_opt_timer.elapsed(), sur_timer.elapsed()); +} + +template +void launch_tests(const char *BoostContName, const char *StdContName) +{ + try { + fill_ranges(); + { + std::cout << "Construct benchmark:" << BoostContName << std::endl; + cpu_times boost_set_time = construct_time< BoostClass >(); + + std::cout << "Construct benchmark:" << StdContName << std::endl; + cpu_times std_set_time = construct_time< StdClass >(); + + std::cout << "Total time (" << BoostContName << "/" << StdContName << "):\n"; + compare_times(boost_set_time, std_set_time); + } + { + std::cout << "Insert benchmark:" << BoostContName << std::endl; + cpu_times boost_set_time = insert_time< BoostClass >(); + + std::cout << "Insert benchmark:" << StdContName << std::endl; + cpu_times std_set_time = insert_time< StdClass >(); + + std::cout << "Total time (" << BoostContName << "/" << StdContName << "):\n"; + compare_times(boost_set_time, std_set_time); + } + { + std::cout << "Search benchmark:" << BoostContName << std::endl; + cpu_times boost_set_time = search_time< BoostClass >(); + + std::cout << "Search benchmark:" << StdContName << std::endl; + cpu_times std_set_time = search_time< StdClass >(); + + std::cout << "Total time (" << BoostContName << "/" << StdContName << "):\n"; + compare_times(boost_set_time, std_set_time); + } + { + std::cout << "Extensions benchmark:" << BoostContName << std::endl; + extensions_time< BoostClass >(); + } + + }catch(std::exception e){ + std::cout << e.what(); + } +} + +int main() +{ + //set vs std::set + launch_tests< boost::container::set , std::set > + ("boost::container::set", "std::set");/* + //multiset vs std::set + launch_tests< boost::container::multiset , std::multiset > + ("boost::container::multiset", "std::multiset");*/ + //flat_set vs set + //launch_tests< boost::container::flat_set , boost::container::set > + //("boost::container::flat_set", "boost::container::set"); + //flat_multiset vs multiset + //launch_tests< boost::container::flat_multiset , boost::container::multiset > + //("boost::container::flat_multiset", "boost::container::multiset"); + return 1; +} diff --git a/bench/bench_static_vector.cpp b/bench/bench_static_vector.cpp index f36e145..71e48a9 100644 --- a/bench/bench_static_vector.cpp +++ b/bench/bench_static_vector.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include diff --git a/bench/detail/varray.hpp b/bench/detail/varray.hpp index e0729f0..874daae 100644 --- a/bench/detail/varray.hpp +++ b/bench/detail/varray.hpp @@ -293,7 +293,7 @@ public: //! @pre count <= capacity() //! - //! @brief Constructs a varray containing count default constructed Values. + //! @brief Constructs a varray containing count value initialized Values. //! //! @param count The number of values which will be contained in the container. //! @@ -616,7 +616,7 @@ public: //! @pre count <= capacity() //! //! @brief Inserts or erases elements at the end such that - //! the size becomes count. New elements are default constructed. + //! the size becomes count. New elements are value initialized. //! //! @param count The number of elements which will be stored in the container. //! diff --git a/bench/varray.hpp b/bench/varray.hpp index 1e15d82..8dcb5de 100644 --- a/bench/varray.hpp +++ b/bench/varray.hpp @@ -91,7 +91,7 @@ public: //! @pre count <= capacity() //! - //! @brief Constructs a varray containing count default constructed Values. + //! @brief Constructs a varray containing count value initialized Values. //! //! @param count The number of values which will be contained in the container. //! @@ -311,7 +311,7 @@ public: //! @pre count <= capacity() //! //! @brief Inserts or erases elements at the end such that - //! the size becomes count. New elements are default constructed. + //! the size becomes count. New elements are value initialized. //! //! @param count The number of elements which will be stored in the container. //! diff --git a/doc/container.qbk b/doc/container.qbk index 1238ce8..0c88b82 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -502,6 +502,52 @@ are a particular case where `static_vector` can be beneficial. [endsect] +[section:extended_functionality Extended functionality] + +[section:default_initialialization Default initialization for vector-like containers] + +STL and most other containers value initialize new elements in common operations like +`vector::resize(size_type n)` or `explicit vector::vector(size_type n)`. + +In some performance-sensitive environments, where vectors are used as a replacement for +variable-size buffers for file or network operations, +[@http://en.cppreference.com/w/cpp/language/value_initialization value initialization] +is a cost that is not negligible as elements are going to be overwritten by an external source +shortly after new elements are added to the container. + +[*Boost.Container] offers two new members for `vector`, `static_vector` and `stable_vector`: +`explicit container::container(size_type n, default_init_t)` and +`explicit container::resize(size_type n, default_init_t)`, where new elements are constructed +using [@http://en.cppreference.com/w/cpp/language/default_initialization default initialization]. + +[endsect] + +[/ +/a__section:get_stored_allocator Obtain stored allocator__a +/ +/STL containers offer a `get_allocator()` member to obtain a copy of the allocator that +/the container is using to allocate and construct elements. For performance reasons, some +/applications need o +/ +/http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html +/ +/a__endsect__a +/ +/a__section:ordered_range_insertion Ordered range insertion (a__'ordered_unique_range__a, a__'ordered_range__a) __a +/ +/a__endsect__a +/ +/a__section:constant_time_range_splice Constant-time range splice__a +/ +/a__endsect__a +/ +/a__section:previous_element_slist Slist previous element__a +/ +/a__endsect__a +/] + +[endsect] + [section:Cpp11_conformance C++11 Conformance] [*Boost.Container] aims for full C++11 conformance except reasoned deviations, diff --git a/include/boost/container/allocator_traits.hpp b/include/boost/container/allocator_traits.hpp index 19c35a8..aa8194a 100644 --- a/include/boost/container/allocator_traits.hpp +++ b/include/boost/container/allocator_traits.hpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -387,6 +388,10 @@ struct allocator_traits #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template + static void priv_construct_dispatch2(boost::false_type, Alloc &, T *p, ::boost::container::default_init_t) + { ::new((void*)p) T; } #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) ///@endcond diff --git a/include/boost/container/container_fwd.hpp b/include/boost/container/container_fwd.hpp index 3b47b2f..271cc8b 100644 --- a/include/boost/container/container_fwd.hpp +++ b/include/boost/container/container_fwd.hpp @@ -135,20 +135,28 @@ class basic_string; struct ordered_range_t {}; +//! Value used to tag that the input range is +//! guaranteed to be ordered +static const ordered_range_t ordered_range = ordered_range_t(); + //! Type used to tag that the input range is //! guaranteed to be ordered and unique struct ordered_unique_range_t : public ordered_range_t {}; -//! Value used to tag that the input range is -//! guaranteed to be ordered -static const ordered_range_t ordered_range = ordered_range_t(); - //! Value used to tag that the input range is //! guaranteed to be ordered and unique static const ordered_unique_range_t ordered_unique_range = ordered_unique_range_t(); +//! Type used to tag that the input range is +//! guaranteed to be ordered and unique +struct default_init_t +{}; + +//! Value used to tag that the input range is +//! guaranteed to be ordered and unique +static const default_init_t default_init = default_init_t(); /// @cond namespace detail_really_deep_namespace { @@ -161,6 +169,7 @@ struct dummy { (void)ordered_range; (void)ordered_unique_range; + (void)default_init; } }; diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index 98b66ee..136b4f6 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -540,7 +540,7 @@ class deque : protected deque_base {} //! Effects: Constructs a deque that will use a copy of allocator a - //! and inserts n default contructed values. + //! and inserts n value initialized values. //! //! Throws: If allocator_type's default constructor or copy constructor //! throws or T's default or copy constructor throws. @@ -549,7 +549,24 @@ class deque : protected deque_base explicit deque(size_type n) : Base(n, allocator_type()) { - container_detail::insert_default_constructed_n_proxy proxy(this->alloc()); + container_detail::insert_value_initialized_n_proxy proxy(this->alloc()); + proxy.uninitialized_copy_n_and_update(this->begin(), n); + //deque_base will deallocate in case of exception... + } + + //! Effects: Constructs a deque that will use a copy of allocator a + //! and inserts n default initialized values. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + //! + //! Note: Non-standard extension + deque(size_type n, default_init_t) + : Base(n, allocator_type()) + { + container_detail::insert_default_initialized_n_proxy proxy(this->alloc()); proxy.uninitialized_copy_n_and_update(this->begin(), n); //deque_base will deallocate in case of exception... } @@ -949,9 +966,9 @@ class deque : protected deque_base { return allocator_traits_type::max_size(this->alloc()); } //! Effects: Inserts or erases elements at the end such that - //! the size becomes n. New elements are default constructed. + //! the size becomes n. New elements are value initialized. //! - //! Throws: If memory allocation throws, or T's copy constructor throws. + //! Throws: If memory allocation throws, or T's constructor throws. //! //! Complexity: Linear to the difference between size() and new_size. void resize(size_type new_size) @@ -961,7 +978,27 @@ class deque : protected deque_base this->priv_erase_last_n(len - new_size); else{ const size_type n = new_size - this->size(); - container_detail::insert_default_constructed_n_proxy proxy(this->alloc()); + container_detail::insert_value_initialized_n_proxy proxy(this->alloc()); + priv_insert_back_aux_impl(n, proxy); + } + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default initialized. + //! + //! Throws: If memory allocation throws, or T's constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + //! + //! Note: Non-standard extension + void resize(size_type new_size, default_init_t) + { + const size_type len = size(); + if (new_size < len) + this->priv_erase_last_n(len - new_size); + else{ + const size_type n = new_size - this->size(); + container_detail::insert_default_initialized_n_proxy proxy(this->alloc()); priv_insert_back_aux_impl(n, proxy); } } diff --git a/include/boost/container/detail/advanced_insert_int.hpp b/include/boost/container/detail/advanced_insert_int.hpp index 47539b3..e42bcb3 100644 --- a/include/boost/container/detail/advanced_insert_int.hpp +++ b/include/boost/container/detail/advanced_insert_int.hpp @@ -99,19 +99,43 @@ struct insert_n_copies_proxy }; template -struct insert_default_constructed_n_proxy +struct insert_value_initialized_n_proxy { typedef ::boost::container::allocator_traits alloc_traits; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::value_type value_type; - explicit insert_default_constructed_n_proxy(A &a) + explicit insert_value_initialized_n_proxy(A &a) : a_(a) {} void uninitialized_copy_n_and_update(Iterator p, size_type n) const - { boost::container::uninitialized_default_alloc_n(this->a_, n, p); } + { boost::container::uninitialized_value_init_alloc_n(this->a_, n, p); } + + void copy_n_and_update(Iterator, size_type) const + { + BOOST_ASSERT(false); + } + + private: + A &a_; +}; + +template +struct insert_default_initialized_n_proxy +{ + typedef ::boost::container::allocator_traits alloc_traits; + typedef typename allocator_traits::size_type size_type; + typedef typename allocator_traits::value_type value_type; + + + explicit insert_default_initialized_n_proxy(A &a) + : a_(a) + {} + + void uninitialized_copy_n_and_update(Iterator p, size_type n) const + { boost::container::uninitialized_default_init_alloc_n(this->a_, n, p); } void copy_n_and_update(Iterator, size_type) const { diff --git a/include/boost/container/detail/algorithms.hpp b/include/boost/container/detail/algorithms.hpp index 072cf9c..7a4a868 100644 --- a/include/boost/container/detail/algorithms.hpp +++ b/include/boost/container/detail/algorithms.hpp @@ -35,13 +35,13 @@ namespace boost { namespace container { template -struct is_default_construct_iterator +struct is_value_init_construct_iterator { static const bool value = false; }; template -struct is_default_construct_iterator > +struct is_value_init_construct_iterator > { static const bool value = true; }; @@ -64,11 +64,17 @@ inline void construct_in_place(A &a, T* dest, InpIt source) //#endif template -inline void construct_in_place(A &a, T *dest, default_construct_iterator) +inline void construct_in_place(A &a, T *dest, value_init_construct_iterator) { boost::container::allocator_traits::construct(a, dest); } +template +inline void construct_in_place(A &a, T *dest, default_init_construct_iterator) +{ + boost::container::allocator_traits::construct(a, dest, default_init); +} + template inline void construct_in_place(A &a, T *dest, emplace_iterator ei) { diff --git a/include/boost/container/detail/allocator_version_traits.hpp b/include/boost/container/detail/allocator_version_traits.hpp index e051707..6df79da 100644 --- a/include/boost/container/detail/allocator_version_traits.hpp +++ b/include/boost/container/detail/allocator_version_traits.hpp @@ -92,8 +92,12 @@ struct allocator_version_traits static void deallocate_individual(Allocator &a, multiallocation_chain &holder) { - while(!holder.empty()){ - a.deallocate(holder.pop_front(), 1); + size_type n = holder.size(); + typename multiallocation_chain::iterator it = holder.begin(); + while(n--){ + pointer p = boost::intrusive::pointer_traits::pointer_to(*it); + ++it; + a.deallocate(p, 1); } } diff --git a/include/boost/container/detail/config_begin.hpp b/include/boost/container/detail/config_begin.hpp index 83c2cfe..664f092 100644 --- a/include/boost/container/detail/config_begin.hpp +++ b/include/boost/container/detail/config_begin.hpp @@ -46,4 +46,5 @@ #pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site #pragma warning (disable : 4671) // the copy constructor is inaccessible #pragma warning (disable : 4584) // X is already a base-class of Y + #pragma warning (disable : 4510) // default constructor could not be generated #endif //BOOST_MSVC diff --git a/include/boost/container/detail/destroyers.hpp b/include/boost/container/detail/destroyers.hpp index 6865466..fef8aa0 100644 --- a/include/boost/container/detail/destroyers.hpp +++ b/include/boost/container/detail/destroyers.hpp @@ -68,6 +68,9 @@ struct scoped_deallocator pointer get() const { return m_ptr; } + void set(const pointer &p) + { m_ptr = p; } + void release() { m_ptr = 0; } }; @@ -87,6 +90,9 @@ struct null_scoped_deallocator pointer get() const { return pointer(); } + + void set(const pointer &) + {} }; //!A deleter for scoped_ptr that deallocates the memory @@ -249,6 +255,11 @@ class scoped_destructor void release() { pv_ = 0; } + + void set(value_type *ptr) { pv_ = ptr; } + + value_type *get() const { return pv_; } + private: value_type *pv_; A &a_; diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 0aad21f..f214d19 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -240,16 +240,24 @@ class flat_tree , const allocator_type& a = allocator_type()) : m_data(comp, a) { + //Use cend() as hint to achieve linear time for + //ordered ranges as required by the standard + //for the constructor + //Call end() every iteration as reallocation might have invalidated iterators if(unique_insertion){ - this->insert_unique(first, last); + for ( ; first != last; ++first){ + this->insert_unique(this->cend(), *first); + } } else{ - this->insert_equal(first, last); + for ( ; first != last; ++first){ + this->insert_equal(this->cend(), *first); + } } } ~flat_tree() - { } + {} flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x) { m_data = x.m_data; return *this; } @@ -389,7 +397,11 @@ class flat_tree template void insert_unique(InIt first, InIt last) - { this->priv_insert_unique_loop(first, last); } + { + for ( ; first != last; ++first){ + this->insert_unique(*first); + } + } template void insert_equal(InIt first, InIt last @@ -487,7 +499,13 @@ class flat_tree >::type * = 0 #endif ) - { this->priv_insert_unique_loop_hint(first, last); } + { + const_iterator pos(this->cend()); + for ( ; first != last; ++first){ + pos = this->insert_unique(pos, *first); + ++pos; + } + } template void insert_unique(ordered_unique_range_t, BidirIt first, BidirIt last @@ -677,22 +695,21 @@ class flat_tree // set operations: iterator find(const key_type& k) { - const Compare &key_cmp = this->m_data.get_comp(); iterator i = this->lower_bound(k); - - if (i != this->end() && key_cmp(k, KeyOfValue()(*i))){ - i = this->end(); + iterator end_it = this->end(); + if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){ + i = end_it; } return i; } const_iterator find(const key_type& k) const { - const Compare &key_cmp = this->m_data.get_comp(); const_iterator i = this->lower_bound(k); - if (i != this->end() && key_cmp(k, KeyOfValue()(*i))){ - i = this->end(); + const_iterator end_it = this->cend(); + if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){ + i = end_it; } return i; } @@ -708,19 +725,19 @@ class flat_tree { return this->priv_lower_bound(this->begin(), this->end(), k); } const_iterator lower_bound(const key_type& k) const - { return this->priv_lower_bound(this->begin(), this->end(), k); } + { return this->priv_lower_bound(this->cbegin(), this->cend(), k); } iterator upper_bound(const key_type& k) { return this->priv_upper_bound(this->begin(), this->end(), k); } const_iterator upper_bound(const key_type& k) const - { return this->priv_upper_bound(this->begin(), this->end(), k); } + { return this->priv_upper_bound(this->cbegin(), this->cend(), k); } std::pair 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); } + { return this->priv_equal_range(this->cbegin(), this->cend(), k); } size_type capacity() const { return this->m_data.m_vect.capacity(); } @@ -817,7 +834,6 @@ class flat_tree //in the remaining range [pos, end) return this->priv_insert_unique_prepare(pos, cend_it, val, commit_data); } - //return priv_insert_unique_prepare(val, commit_data); } template @@ -835,11 +851,11 @@ class flat_tree { const Compare &key_cmp = this->m_data.get_comp(); KeyOfValue key_extract; - difference_type len = last - first, half; + size_type len = static_cast(last - first); RanIt middle; - while (len > 0) { - half = len >> 1; + while (len) { + size_type half = len >> 1; middle = first; middle += half; @@ -854,17 +870,18 @@ class flat_tree return first; } + template RanIt priv_upper_bound(RanIt first, RanIt last, const key_type & key) const { const Compare &key_cmp = this->m_data.get_comp(); KeyOfValue key_extract; - difference_type len = last - first, half; + size_type len = static_cast(last - first); RanIt middle; - while (len > 0) { - half = len >> 1; + while (len) { + size_type half = len >> 1; middle = first; middle += half; @@ -885,11 +902,11 @@ class flat_tree { const Compare &key_cmp = this->m_data.get_comp(); KeyOfValue key_extract; - difference_type len = last - first, half; - RanIt middle, left, right; + size_type len = static_cast(last - first); + RanIt middle; - while (len > 0) { - half = len >> 1; + while (len) { + size_type half = len >> 1; middle = first; middle += half; @@ -902,10 +919,11 @@ class flat_tree 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); + //Middle is equal to key + last = first; + last += len; + first = this->priv_lower_bound(first, middle, key); + return std::pair (first, this->priv_upper_bound(++middle, last, key)); } } return std::pair(first, first); @@ -924,24 +942,10 @@ class flat_tree { const_iterator pos(this->cend()); for ( ; first != last; ++first){ + //If ordered, then try hint version + //to achieve constant-time complexity per insertion pos = this->insert_equal(pos, *first); - } - } - - template - void priv_insert_unique_loop(InIt first, InIt last) - { - for ( ; first != last; ++first){ - this->insert_unique(*first); - } - } - - template - void priv_insert_unique_loop_ordered(InIt first, InIt last) - { - const_iterator pos(this->cend()); - for ( ; first != last; ++first){ - pos = this->insert_unique(pos, *first); + ++pos; } } }; diff --git a/include/boost/container/detail/iterators.hpp b/include/boost/container/detail/iterators.hpp index 500e6b9..5766a7c 100644 --- a/include/boost/container/detail/iterators.hpp +++ b/include/boost/container/detail/iterators.hpp @@ -148,79 +148,79 @@ class constant_iterator }; template -class default_construct_iterator +class value_init_construct_iterator : public std::iterator { - typedef default_construct_iterator this_type; + typedef value_init_construct_iterator this_type; public: - explicit default_construct_iterator(Difference range_size) + explicit value_init_construct_iterator(Difference range_size) : m_num(range_size){} //Constructors - default_construct_iterator() + value_init_construct_iterator() : m_num(0){} - default_construct_iterator& operator++() + value_init_construct_iterator& operator++() { increment(); return *this; } - default_construct_iterator operator++(int) + value_init_construct_iterator operator++(int) { - default_construct_iterator result (*this); + value_init_construct_iterator result (*this); increment(); return result; } - default_construct_iterator& operator--() + value_init_construct_iterator& operator--() { decrement(); return *this; } - default_construct_iterator operator--(int) + value_init_construct_iterator operator--(int) { - default_construct_iterator result (*this); + value_init_construct_iterator result (*this); decrement(); return result; } - friend bool operator== (const default_construct_iterator& i, const default_construct_iterator& i2) + friend bool operator== (const value_init_construct_iterator& i, const value_init_construct_iterator& i2) { return i.equal(i2); } - friend bool operator!= (const default_construct_iterator& i, const default_construct_iterator& i2) + friend bool operator!= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2) { return !(i == i2); } - friend bool operator< (const default_construct_iterator& i, const default_construct_iterator& i2) + friend bool operator< (const value_init_construct_iterator& i, const value_init_construct_iterator& i2) { return i.less(i2); } - friend bool operator> (const default_construct_iterator& i, const default_construct_iterator& i2) + friend bool operator> (const value_init_construct_iterator& i, const value_init_construct_iterator& i2) { return i2 < i; } - friend bool operator<= (const default_construct_iterator& i, const default_construct_iterator& i2) + friend bool operator<= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2) { return !(i > i2); } - friend bool operator>= (const default_construct_iterator& i, const default_construct_iterator& i2) + friend bool operator>= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2) { return !(i < i2); } - friend Difference operator- (const default_construct_iterator& i, const default_construct_iterator& i2) + friend Difference operator- (const value_init_construct_iterator& i, const value_init_construct_iterator& i2) { return i2.distance_to(i); } //Arithmetic - default_construct_iterator& operator+=(Difference off) + value_init_construct_iterator& operator+=(Difference off) { this->advance(off); return *this; } - default_construct_iterator operator+(Difference off) const + value_init_construct_iterator operator+(Difference off) const { - default_construct_iterator other(*this); + value_init_construct_iterator other(*this); other.advance(off); return other; } - friend default_construct_iterator operator+(Difference off, const default_construct_iterator& right) + friend value_init_construct_iterator operator+(Difference off, const value_init_construct_iterator& right) { return right + off; } - default_construct_iterator& operator-=(Difference off) + value_init_construct_iterator& operator-=(Difference off) { this->advance(-off); return *this; } - default_construct_iterator operator-(Difference off) const + value_init_construct_iterator operator-(Difference off) const { return *this + (-off); } //This pseudo-iterator's dereference operations have no sense since value is not @@ -258,6 +258,118 @@ class default_construct_iterator { return m_num - other.m_num; } }; +template +class default_init_construct_iterator + : public std::iterator + +{ + typedef default_init_construct_iterator this_type; + + public: + explicit default_init_construct_iterator(Difference range_size) + : m_num(range_size){} + + //Constructors + default_init_construct_iterator() + : m_num(0){} + + default_init_construct_iterator& operator++() + { increment(); return *this; } + + default_init_construct_iterator operator++(int) + { + default_init_construct_iterator result (*this); + increment(); + return result; + } + + default_init_construct_iterator& operator--() + { decrement(); return *this; } + + default_init_construct_iterator operator--(int) + { + default_init_construct_iterator result (*this); + decrement(); + return result; + } + + friend bool operator== (const default_init_construct_iterator& i, const default_init_construct_iterator& i2) + { return i.equal(i2); } + + friend bool operator!= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2) + { return !(i == i2); } + + friend bool operator< (const default_init_construct_iterator& i, const default_init_construct_iterator& i2) + { return i.less(i2); } + + friend bool operator> (const default_init_construct_iterator& i, const default_init_construct_iterator& i2) + { return i2 < i; } + + friend bool operator<= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2) + { return !(i > i2); } + + friend bool operator>= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2) + { return !(i < i2); } + + friend Difference operator- (const default_init_construct_iterator& i, const default_init_construct_iterator& i2) + { return i2.distance_to(i); } + + //Arithmetic + default_init_construct_iterator& operator+=(Difference off) + { this->advance(off); return *this; } + + default_init_construct_iterator operator+(Difference off) const + { + default_init_construct_iterator other(*this); + other.advance(off); + return other; + } + + friend default_init_construct_iterator operator+(Difference off, const default_init_construct_iterator& right) + { return right + off; } + + default_init_construct_iterator& operator-=(Difference off) + { this->advance(-off); return *this; } + + default_init_construct_iterator operator-(Difference off) const + { return *this + (-off); } + + //This pseudo-iterator's dereference operations have no sense since value is not + //constructed until ::boost::container::construct_in_place is called. + //So comment them to catch bad uses + //const T& operator*() const; + //const T& operator[](difference_type) const; + //const T* operator->() const; + + private: + Difference m_num; + + void increment() + { --m_num; } + + void decrement() + { ++m_num; } + + bool equal(const this_type &other) const + { return m_num == other.m_num; } + + bool less(const this_type &other) const + { return other.m_num < m_num; } + + const T & dereference() const + { + static T dummy; + return dummy; + } + + void advance(Difference n) + { m_num -= n; } + + Difference distance_to(const this_type &other)const + { return m_num - other.m_num; } +}; + + template class repeat_iterator : public std::iterator diff --git a/include/boost/container/detail/multiallocation_chain.hpp b/include/boost/container/detail/multiallocation_chain.hpp index 2e29f9c..bc9945a 100644 --- a/include/boost/container/detail/multiallocation_chain.hpp +++ b/include/boost/container/detail/multiallocation_chain.hpp @@ -243,10 +243,10 @@ class transform_multiallocation_chain iterator before_begin() { return iterator(holder_.before_begin()); } - +*/ iterator begin() - { return iterator(holder_.begin()); } - + { return iterator(this->MultiallocationChain::begin()); } +/* iterator end() { return iterator(holder_.end()); } diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index 4ab26c9..d94c2e9 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,7 @@ struct node_alloc_holder typedef typename allocator_traits_type::template portable_rebind_alloc::type NodeAlloc; typedef allocator_traits node_allocator_traits_type; + typedef container_detail::allocator_version_traits node_allocator_version_traits_type; typedef A ValAlloc; typedef typename node_allocator_traits_type::pointer NodePtr; typedef container_detail::scoped_deallocator Deallocator; @@ -233,45 +235,41 @@ struct node_alloc_holder (FwdIterator beg, difference_type n, Inserter inserter) { if(n){ - /* - NodePtr p = this->allocate_one(); - Deallocator node_deallocator(p, this->node_alloc()); - ::boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), it); - node_deallocator.release(); - //This does not throw - typedef typename Node::hook_type hook_type; - ::new(static_cast(container_detail::to_raw_pointer(p))) hook_type; - return (p); - */ - typedef typename NodeAlloc::multiallocation_chain multiallocation_chain; + typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain; //Try to allocate memory in a single block typedef typename multiallocation_chain::iterator multialloc_iterator; multiallocation_chain mem; - this->node_alloc().allocate_individual(n, mem); + NodeAlloc &nalloc = this->node_alloc(); + node_allocator_version_traits_type::allocate_individual(nalloc, n, mem); multialloc_iterator itbeg(mem.begin()), itlast(mem.last()); mem.clear(); Node *p = 0; - NodeAlloc &nalloc = this->node_alloc(); BOOST_TRY{ + Deallocator node_deallocator(NodePtr(), nalloc); + container_detail::scoped_destructor sdestructor(nalloc, 0); while(n--){ p = container_detail::to_raw_pointer(&*itbeg); + node_deallocator.set(p); ++itbeg; //This can throw - Deallocator node_deallocator(p, nalloc); boost::container::construct_in_place(nalloc, container_detail::addressof(p->m_data), beg); + sdestructor.set(p); ++beg; - node_deallocator.release(); //This does not throw typedef typename Node::hook_type hook_type; ::new(static_cast(p)) hook_type; - //This can throw in some containers (predicate might throw) + //This can throw in some containers (predicate might throw). + //(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception) inserter(*p); + sdestructor.set(0); } + sdestructor.release(); + node_deallocator.release(); } BOOST_CATCH(...){ mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n); - this->node_alloc().deallocate_individual(mem); + node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), mem); BOOST_RETHROW } BOOST_CATCH_END diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 6dcb1b7..2c3fdde 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -178,6 +178,34 @@ struct rbtree_node { m_data = ::boost::move(v); } }; +template +class insert_equal_end_hint_functor +{ + Icont &icont_; + + public: + insert_equal_end_hint_functor(Icont &icont) + : icont_(icont) + {} + + void operator()(Node &n) + { this->icont_.insert_equal(this->icont_.cend(), n); } +}; + +template +class push_back_functor +{ + Icont &icont_; + + public: + push_back_functor(Icont &icont) + : icont_(icont) + {} + + void operator()(Node &n) + { this->icont_.push_back(n); } +}; + }//namespace container_detail { namespace container_detail { @@ -405,11 +433,19 @@ class rbtree ) : AllocHolder(a, value_compare(comp)) { + //Use cend() as hint to achieve linear time for + //ordered ranges as required by the standard + //for the constructor + const const_iterator end_it(this->cend()); if(unique_insertion){ - this->insert_unique(first, last); + for ( ; first != last; ++first){ + this->insert_unique(end_it, *first); + } } else{ - this->insert_equal(first, last); + for ( ; first != last; ++first){ + this->insert_equal(end_it, *first); + } } } @@ -426,12 +462,19 @@ class rbtree : AllocHolder(a, value_compare(comp)) { if(unique_insertion){ - this->insert_unique(first, last); + //Use cend() as hint to achieve linear time for + //ordered ranges as required by the standard + //for the constructor + const const_iterator end_it(this->cend()); + for ( ; first != last; ++first){ + this->insert_unique(end_it, *first); + } } else{ //Optimized allocation and construction this->allocate_many_and_construct - (first, std::distance(first, last), insert_equal_end_hint_functor(this->icont())); + ( first, std::distance(first, last) + , insert_equal_end_hint_functor(this->icont())); } } @@ -447,7 +490,9 @@ class rbtree ) : AllocHolder(a, value_compare(comp)) { - this->insert_equal(first, last); + for ( ; first != last; ++first){ + this->push_back_impl(*first); + } } template @@ -464,7 +509,8 @@ class rbtree { //Optimized allocation and construction this->allocate_many_and_construct - (first, std::distance(first, last), push_back_functor(this->icont())); + ( first, std::distance(first, last) + , container_detail::push_back_functor(this->icont())); } rbtree(const rbtree& x) @@ -534,8 +580,8 @@ class rbtree rbtree& operator=(BOOST_RV_REF(rbtree) x) { if (&x != this){ - NodeAlloc &this_alloc = this->node_alloc(); - NodeAlloc &x_alloc = x.node_alloc(); + NodeAlloc &this_alloc = this->get_stored_allocator(); + const NodeAlloc &x_alloc = x.get_stored_allocator(); //If allocators are equal we can just swap pointers if(this_alloc == x_alloc){ //Destroy and swap pointers @@ -678,8 +724,10 @@ class rbtree iterator insert_unique_commit(const value_type& v, insert_commit_data &data) { NodePtr tmp = AllocHolder::create_node(v); - iiterator it(this->icont().insert_unique_commit(*tmp, data)); - return iterator(it); + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + iterator ret(this->icont().insert_unique_commit(*tmp, data)); + destroy_deallocator.release(); + return ret; } template @@ -687,8 +735,10 @@ class rbtree (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); + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + iterator ret(this->icont().insert_unique_commit(*tmp, data)); + destroy_deallocator.release(); + return ret; } std::pair insert_unique(const value_type& v) @@ -696,10 +746,10 @@ class rbtree 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); + if(ret.second){ + ret.first = this->insert_unique_commit(v, data); + } + return ret; } template @@ -708,13 +758,22 @@ class rbtree 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); + if(ret.second){ + ret.first = this->insert_unique_commit(boost::forward(mv), data); + } + return ret; } private: + + template + void push_back_impl(BOOST_FWD_REF(MovableConvertible) mv) + { + NodePtr tmp(AllocHolder::create_node(boost::forward(mv))); + //push_back has no-throw guarantee so avoid any deallocator/destroyer + this->icont().push_back(*tmp); + } + std::pair emplace_unique_impl(NodePtr p) { value_type &v = p->get_data(); @@ -760,15 +819,21 @@ class rbtree template iterator emplace_equal(Args&&... args) { - NodePtr p(AllocHolder::create_node(boost::forward(args)...)); - return iterator(this->icont().insert_equal(this->icont().end(), *p)); + NodePtr tmp(AllocHolder::create_node(boost::forward(args)...)); + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); + destroy_deallocator.release(); + return ret; } 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)); + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + iterator ret(this->icont().insert_equal(hint.get(), *tmp)); + destroy_deallocator.release(); + return ret; } #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING @@ -792,16 +857,22 @@ class rbtree BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ { \ - NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - return iterator(this->icont().insert_equal(this->icont().end(), *p)); \ + NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); \ + iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); \ + destroy_deallocator.release(); \ + return ret; \ } \ \ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ iterator emplace_hint_equal(const_iterator hint \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ { \ - NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - return iterator(this->icont().insert_equal(hint.get(), *p)); \ + NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); \ + iterator ret(this->icont().insert_equal(hint.get(), *tmp)); \ + destroy_deallocator.release(); \ + return ret; \ } \ //! #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) @@ -833,53 +904,53 @@ class rbtree 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 hint(this->cend()); - for( ; first != last; ++first) - hint = this->insert_unique(hint, *first); - } - else{ - for( ; first != last; ++first) - this->insert_unique(*first); - } + for( ; first != last; ++first) + this->insert_unique(*first); } iterator insert_equal(const value_type& v) { - NodePtr p(AllocHolder::create_node(v)); - return iterator(this->icont().insert_equal(this->icont().end(), *p)); + NodePtr tmp(AllocHolder::create_node(v)); + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); + destroy_deallocator.release(); + return ret; } 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)); + NodePtr tmp(AllocHolder::create_node(boost::forward(mv))); + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); + destroy_deallocator.release(); + return ret; } iterator insert_equal(const_iterator hint, const value_type& v) { - NodePtr p(AllocHolder::create_node(v)); - return iterator(this->icont().insert_equal(hint.get(), *p)); + NodePtr tmp(AllocHolder::create_node(v)); + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + iterator ret(this->icont().insert_equal(hint.get(), *tmp)); + destroy_deallocator.release(); + return ret; } 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)); + NodePtr tmp(AllocHolder::create_node(boost::forward(mv))); + scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + iterator ret(this->icont().insert_equal(hint.get(), *tmp)); + destroy_deallocator.release(); + return ret; } template void insert_equal(InputIterator first, InputIterator last) { - //Insert with end hint, to achieve linear - //complexity if [first, last) is ordered - const_iterator hint(this->cend()); for( ; first != last; ++first) - hint = this->insert_equal(hint, *first); + this->insert_equal(*first); } iterator erase(const_iterator position) @@ -930,41 +1001,6 @@ class rbtree return std::pair (const_iterator(ret.first), const_iterator(ret.second)); } - - private: - - class insert_equal_end_hint_functor; - friend class insert_equal_end_hint_functor; - - class insert_equal_end_hint_functor - { - Icont &icont_; - const iconst_iterator cend_; - - public: - insert_equal_end_hint_functor(Icont &icont) - : icont_(icont), cend_(this->icont_.cend()) - {} - - void operator()(Node &n) - { this->icont_.insert_equal(cend_, n); } - }; - - class push_back_functor; - friend class push_back_functor; - - class push_back_functor - { - Icont &icont_; - - public: - push_back_functor(Icont &icont) - : icont_(icont) - {} - - void operator()(Node &n) - { this->icont_.push_back(n); } - }; }; template :: ////////////////////////////////////////////////////////////////////////////// // -// uninitialized_default_alloc_n +// uninitialized_value_init_alloc_n // ////////////////////////////////////////////////////////////////////////////// @@ -636,7 +636,7 @@ inline typename container_detail::enable_if_memcpy_copy_constructible:: template // F models ForwardIterator -inline F uninitialized_default_alloc_n(A &a, typename allocator_traits::difference_type n, F r) +inline F uninitialized_value_init_alloc_n(A &a, typename allocator_traits::difference_type n, F r) { F back = r; BOOST_TRY{ @@ -655,6 +655,41 @@ inline F uninitialized_default_alloc_n(A &a, typename allocator_traits::diffe return r; } +////////////////////////////////////////////////////////////////////////////// +// +// uninitialized_default_init_alloc_n +// +////////////////////////////////////////////////////////////////////////////// + +//! Effects: +//! \code +//! for (; n--; ++r, ++f) +//! allocator_traits::construct(a, &*r); +//! \endcode +//! +//! Returns: r +template + // F models ForwardIterator +inline F uninitialized_default_init_alloc_n(A &a, typename allocator_traits::difference_type n, F r) +{ + F back = r; + BOOST_TRY{ + while (n--) { + allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), default_init); + ++r; + } + } + BOOST_CATCH(...){ + for (; back != r; ++back){ + allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); + } + BOOST_RETHROW; + } + BOOST_CATCH_END + return r; +} + ////////////////////////////////////////////////////////////////////////////// // // uninitialized_fill_alloc diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 9da14c9..8778de5 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -694,6 +694,8 @@ class flat_map //! search time plus N*size() insertion time. //! //! Note: If an element is inserted it might invalidate elements. + //! + //! Note: Non-standard extension. template void insert(ordered_unique_range_t, InputIterator first, InputIterator last) { m_flat_tree.insert_unique(ordered_unique_range, first, last); } @@ -798,7 +800,7 @@ class flat_map //! //! 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; } + { return static_cast(m_flat_tree.find(x) != m_flat_tree.end()); } //! Returns: An iterator pointing to the first element with key not less //! than k, or a.end() if such an element is not found. @@ -1487,6 +1489,8 @@ class flat_multimap //! search time plus N*size() insertion time. //! //! Note: If an element is inserted it might invalidate elements. + //! + //! Note: Non-standard extension. template void insert(ordered_range_t, InputIterator first, InputIterator last) { m_flat_tree.insert_equal(ordered_range, first, last); } diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 77711cc..eda8fbd 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -636,7 +636,7 @@ class flat_set //! //! 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; } + { return static_cast(m_flat_tree.find(x) != m_flat_tree.end()); } //! Returns: An iterator pointing to the first element with key not less //! than k, or a.end() if such an element is not found. diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 2eff808..8ebd5be 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -563,7 +563,7 @@ class list { return AllocHolder::max_size(); } //! Effects: Inserts or erases elements at the end such that - //! the size becomes n. New elements are default constructed. + //! the size becomes n. New elements are value initialized. //! //! Throws: If memory allocation throws, or T's copy constructor throws. //! @@ -571,8 +571,8 @@ class list void resize(size_type new_size) { if(!priv_try_shrink(new_size)){ - typedef default_construct_iterator default_iterator; - this->insert(this->cend(), default_iterator(new_size - this->size()), default_iterator()); + typedef value_init_construct_iterator value_init_iterator; + this->insert(this->cend(), value_init_iterator(new_size - this->size()), value_init_iterator()); } } diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index e0b5581..f4776e8 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -170,6 +170,8 @@ class map //! unique values. //! //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. template map( ordered_unique_range_t, InputIterator first, InputIterator last , const Compare& comp = Compare(), const allocator_type& a = allocator_type()) @@ -711,7 +713,7 @@ class map //! //! Complexity: log(size())+count(k) size_type count(const key_type& x) const - { return m_tree.find(x) == m_tree.end() ? 0 : 1; } + { return static_cast(m_tree.find(x) != m_tree.end()); } //! Returns: An iterator pointing to the first element with key not less //! than k, or a.end() if such an element is not found. @@ -971,6 +973,8 @@ class multimap //! Requires: [first ,last) must be ordered according to the predicate. //! //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. template multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index d215df4..96656f3 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -139,6 +139,8 @@ class set //! unique values. //! //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. template set( ordered_unique_range_t, InputIterator first, InputIterator last , const Compare& comp = Compare(), const allocator_type& a = allocator_type()) @@ -556,7 +558,7 @@ class set //! //! Complexity: log(size())+count(k) size_type count(const key_type& x) const - { return m_tree.find(x) == m_tree.end() ? 0 : 1; } + { return static_cast(m_tree.find(x) != m_tree.end()); } //! Returns: An iterator pointing to the first element with key not less //! than k, or a.end() if such an element is not found. @@ -770,6 +772,8 @@ class multiset //! Requires: [first ,last) must be ordered according to the predicate. //! //! Complexity: Linear in N. + //! + //! Note: Non-standard extension. template multiset( ordered_range_t, InputIterator first, InputIterator last , const Compare& comp = Compare() diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index 37a3b52..9d2d761 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -588,7 +588,7 @@ class slist { return AllocHolder::max_size(); } //! Effects: Inserts or erases elements at the end such that - //! the size becomes n. New elements are default constructed. + //! the size becomes n. New elements are value initialized. //! //! Throws: If memory allocation throws, or T's copy constructor throws. //! @@ -597,8 +597,8 @@ class slist { const_iterator last_pos; if(!priv_try_shrink(new_size, last_pos)){ - typedef default_construct_iterator default_iterator; - this->insert_after(last_pos, default_iterator(new_size - this->size()), default_iterator()); + typedef value_init_construct_iterator value_init_iterator; + this->insert_after(last_pos, value_init_iterator(new_size - this->size()), value_init_iterator()); } } diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index c64a339..7b31cc4 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -123,8 +123,8 @@ struct node rebind_pointer::type > { - private: - node(); +// private: +// node(); public: typename ::boost::intrusive::pointer_traits::element_type value; @@ -568,7 +568,7 @@ class stable_vector } //! Effects: Constructs a stable_vector that will use a copy of allocator a - //! and inserts n default contructed values. + //! and inserts n value initialized values. //! //! Throws: If allocator_type's default constructor or copy constructor //! throws or T's default or copy constructor throws. @@ -583,6 +583,24 @@ class stable_vector cod.release(); } + //! Effects: Constructs a stable_vector that will use a copy of allocator a + //! and inserts n default initialized values. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + //! + //! Note: Non-standard extension + stable_vector(size_type n, default_init_t) + : internal_data(), index() + { + stable_vector_detail::clear_on_destroy cod(*this); + this->resize(n, default_init); + 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. //! @@ -960,17 +978,35 @@ class stable_vector { return this->index.max_size() - ExtraPointers; } //! Effects: Inserts or erases elements at the end such that - //! the size becomes n. New elements are default constructed. + //! the size becomes n. New elements are value initialized. //! - //! Throws: If memory allocation throws, or T's copy constructor throws. + //! Throws: If memory allocation throws, or T's default constructor throws. //! //! Complexity: Linear to the difference between size() and new_size. void resize(size_type n) { - typedef default_construct_iterator default_iterator; + typedef value_init_construct_iterator value_init_iterator; STABLE_VECTOR_CHECK_INVARIANT; if(n > this->size()) - this->insert(this->cend(), default_iterator(n - this->size()), default_iterator()); + this->insert(this->cend(), value_init_iterator(n - this->size()), value_init_iterator()); + else if(n < this->size()) + this->erase(this->cbegin() + n, this->cend()); + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default initialized. + //! + //! Throws: If memory allocation throws, or T's default constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + //! + //! Note: Non-standard extension + void resize(size_type n, default_init_t) + { + typedef default_init_construct_iterator default_init_iterator; + STABLE_VECTOR_CHECK_INVARIANT; + if(n > this->size()) + this->insert(this->cend(), default_init_iterator(n - this->size()), default_init_iterator()); else if(n < this->size()) this->erase(this->cbegin() + n, this->cend()); } diff --git a/include/boost/container/static_vector.hpp b/include/boost/container/static_vector.hpp index 17aafc2..6ca0f4f 100644 --- a/include/boost/container/static_vector.hpp +++ b/include/boost/container/static_vector.hpp @@ -138,7 +138,7 @@ public: //! @pre count <= capacity() //! - //! @brief Constructs a static_vector containing count default constructed Values. + //! @brief Constructs a static_vector containing count value initialized values. //! //! @param count The number of values which will be contained in the container. //! @@ -151,6 +151,24 @@ public: : base_t(count) {} + //! @pre count <= capacity() + //! + //! @brief Constructs a static_vector containing count value initialized values. + //! + //! @param count The number of values which will be contained in the container. + //! + //! @par Throws + //! If Value's default constructor throws. + //! + //! @par Complexity + //! Linear O(N). + //! + //! @par Note + //! Non-standard extension + static_vector(size_type count, default_init_t) + : base_t(count, default_init_t()) + {} + //! @pre count <= capacity() //! //! @brief Constructs a static_vector containing count copies of value. @@ -358,7 +376,7 @@ public: //! @pre count <= capacity() //! //! @brief Inserts or erases elements at the end such that - //! the size becomes count. New elements are default constructed. + //! the size becomes count. New elements are value initialized. //! //! @param count The number of elements which will be stored in the container. //! @@ -369,6 +387,23 @@ public: //! Linear O(N). void resize(size_type count); + //! @pre count <= capacity() + //! + //! @brief Inserts or erases elements at the end such that + //! the size becomes count. New elements are default initialized. + //! + //! @param count The number of elements which will be stored in the container. + //! + //! @par Throws + //! If Value's default constructor throws. + //! + //! @par Complexity + //! Linear O(N). + //! + //! @par Note + //! Non-standard extension + void resize(size_type count, default_init_t); + //! @pre count <= capacity() //! //! @brief Inserts or erases elements at the end such that diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index 197bb85..e006326 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -937,7 +937,7 @@ class basic_string } //! Effects: Inserts or erases elements at the end such that - //! the size becomes n. New elements are default constructed. + //! the size becomes n. New elements are value initialized. //! //! Throws: If memory allocation throws //! diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 97a1ceb..eabcab9 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -293,18 +293,26 @@ struct vector_alloc_holder template explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a, size_type initial_size) : Allocator(boost::forward(a)) + , m_start() , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this + , m_capacity() { - m_start = this->allocation_command(allocate_new, initial_size, initial_size, m_capacity, m_start).first; + if(initial_size){ + m_start = this->allocation_command(allocate_new, initial_size, initial_size, m_capacity, m_start).first; + } } //Constructor, does not throw explicit vector_alloc_holder(size_type initial_size) : Allocator() + , m_start() , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this + , m_capacity() { - m_start = this->allocation_command - (allocate_new, initial_size, initial_size, m_capacity, m_start).first; + if(initial_size){ + m_start = this->allocation_command + (allocate_new, initial_size, initial_size, m_capacity, m_start).first; + } } vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_CONTAINER_NOEXCEPT @@ -319,8 +327,10 @@ struct vector_alloc_holder void first_allocation(size_type cap) { - m_start = this->allocation_command - (allocate_new, cap, cap, m_capacity, m_start).first; + if(cap){ + m_start = this->allocation_command + (allocate_new, cap, cap, m_capacity, m_start).first; + } } void first_allocation_same_allocator_type(size_type cap) @@ -417,16 +427,18 @@ struct vector_alloc_holder explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a, size_type initial_size) : Allocator(boost::forward(a)) - , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this + , m_size(initial_size) //Size is initialized here... { + //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor this->first_allocation(initial_size); } //Constructor, does not throw explicit vector_alloc_holder(size_type initial_size) : Allocator() - , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this + , m_size(initial_size) //Size is initialized here... { + //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor this->first_allocation(initial_size); } @@ -611,7 +623,7 @@ class vector {} //! Effects: Constructs a vector that will use a copy of allocator a - //! and inserts n default contructed values. + //! and inserts n value initialized values. //! //! Throws: If allocator_type's default constructor or allocation //! throws or T's default constructor throws. @@ -620,7 +632,24 @@ class vector explicit vector(size_type n) : m_holder(n) { - boost::container::uninitialized_default_alloc_n(this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); + boost::container::uninitialized_value_init_alloc_n + (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); + } + + //! Effects: Constructs a vector that will use a copy of allocator a + //! and inserts n default initialized values. + //! + //! Throws: If allocator_type's default constructor or allocation + //! throws or T's default constructor throws. + //! + //! Complexity: Linear to n. + //! + //! Note: Non-standard extension + explicit vector(size_type n, default_init_t) + : m_holder(n) + { + boost::container::uninitialized_default_init_alloc_n + (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); } //! Effects: Constructs a vector @@ -1030,9 +1059,9 @@ class vector { return allocator_traits_type::max_size(this->m_holder.alloc()); } //! Effects: Inserts or erases elements at the end such that - //! the size becomes n. New elements are default constructed. + //! the size becomes n. New elements are value initialized. //! - //! Throws: If memory allocation throws, or T's copy constructor throws. + //! Throws: If memory allocation throws, or T's constructor throws. //! //! Complexity: Linear to the difference between size() and new_size. void resize(size_type new_size) @@ -1044,7 +1073,29 @@ class vector } else{ const size_type n = new_size - this->size(); - container_detail::insert_default_constructed_n_proxy proxy(this->m_holder.alloc()); + container_detail::insert_value_initialized_n_proxy proxy(this->m_holder.alloc()); + this->priv_forward_range_insert_at_end(n, proxy, alloc_version()); + } + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are value initialized. + //! + //! Throws: If memory allocation throws, or T's constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + //! + //! Note: Non-standard extension + void resize(size_type new_size, default_init_t) + { + const size_type sz = this->size(); + if (new_size < sz){ + //Destroy last elements + this->priv_destroy_last_n(sz - new_size); + } + else{ + const size_type n = new_size - this->size(); + container_detail::insert_default_initialized_n_proxy proxy(this->m_holder.alloc()); this->priv_forward_range_insert_at_end(n, proxy, alloc_version()); } } diff --git a/proj/vc7ide/bench_set.vcproj b/proj/vc7ide/bench_set.vcproj new file mode 100644 index 0000000..327e6fe --- /dev/null +++ b/proj/vc7ide/bench_set.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/container.sln b/proj/vc7ide/container.sln index 082bf1d..0953f18 100644 --- a/proj/vc7ide/container.sln +++ b/proj/vc7ide/container.sln @@ -67,6 +67,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_static_vector", "benc ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_set", "bench_set.vcproj", "{5E1C1C23-26A9-4FE5-A24E-DA735271C32B}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -137,12 +141,14 @@ Global {5A8D91E0-FA57-284F-84FE-D3A6BA792002}.Release.Build.0 = Release|Win32 {58E1C1C3-096A-84FE-4FA2-D6BA79201C02}.Debug.ActiveCfg = Debug|Win32 {58E1C1C3-096A-84FE-4FA2-D6BA79201C02}.Debug.Build.0 = Debug|Win32 - {58E1C1C3-096A-84F0-4FA2-D6BA79201C02}.Release.ActiveCfg = Release|Win32 - {58E1C1C3-096A-84F0-4FA2-D6BA79201C02}.Release.Build.0 = Release|Win32 - {58E1C1C3-096A-84F1-4FA2-D6BA79201C02}.Debug.ActiveCfg = Debug|Win32 - {58E1C1C3-096A-84F1-4FA2-D6BA79201C02}.Debug.Build.0 = Debug|Win32 - {58E1C1C3-096A-84F2-4FA2-D6BA79201C02}.Release.ActiveCfg = Release|Win32 - {58E1C1C3-096A-84F2-4FA2-D6BA79201C02}.Release.Build.0 = Release|Win32 + {58E1C1C3-096A-84FE-4FA2-D6BA79201C02}.Release.ActiveCfg = Release|Win32 + {58E1C1C3-096A-84FE-4FA2-D6BA79201C02}.Debug.ActiveCfg = Debug|Win32 + {58E1C1C3-096A-84FE-4FA2-D6BA79201C02}.Debug.Build.0 = Debug|Win32 + {58E1C1C3-096A-84FE-4FA2-D6BA79201C02}.Release.ActiveCfg = Release|Win32 + {5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Debug.ActiveCfg = Debug|Win32 + {5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Debug.Build.0 = Debug|Win32 + {5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Release.ActiveCfg = Release|Win32 + {5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/container.vcproj b/proj/vc7ide/container.vcproj index 185a5c0..8841324 100644 --- a/proj/vc7ide/container.vcproj +++ b/proj/vc7ide/container.vcproj @@ -337,6 +337,9 @@ + + diff --git a/test/allocator_traits_test.cpp b/test/allocator_traits_test.cpp index 3161884..119ec72 100644 --- a/test/allocator_traits_test.cpp +++ b/test/allocator_traits_test.cpp @@ -25,6 +25,12 @@ class SimpleAllocator public: typedef T value_type; + template + SimpleAllocator(SimpleAllocator) + : allocate_called_(false) + , deallocate_called_(false) + {} + SimpleAllocator() : allocate_called_(false) , deallocate_called_(false) @@ -132,6 +138,13 @@ class ComplexAllocator #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() + template + void construct(U *p, boost::container::default_init_t) + { + construct_called_ = true; + ::new (p) U; + } + //getters bool allocate_called() const { return allocate_called_; } @@ -157,13 +170,13 @@ class ComplexAllocator class copymovable { - bool copymoveconstructed_; - bool moved_; - BOOST_COPYABLE_AND_MOVABLE(copymovable) public: + bool copymoveconstructed_; + bool moved_; + copymovable(int, int, int) : copymoveconstructed_(false), moved_(false) {} @@ -314,6 +327,22 @@ int main() SAllocTraits::select_on_container_copy_construction(s_alloc); //construct + { + copymovable c; + c.copymoveconstructed_ = true; + c.copymoveconstructed_ = true; + CAllocTraits::construct(c_alloc, &c); + if(!c_alloc.construct_called() || c.copymoveconstructed() || c.moved()){ + return 1; + } + } + { + int i = 5; + CAllocTraits::construct(c_alloc, &i, boost::container::default_init); + if(!c_alloc.construct_called() || i != 5){ + return 1; + } + } { copymovable c; copymovable c2; @@ -330,6 +359,22 @@ int main() return 1; } } + { + copymovable c; + c.copymoveconstructed_ = true; + c.copymoveconstructed_ = true; + SAllocTraits::construct(s_alloc, &c); + if(c.copymoveconstructed() || c.moved()){ + return 1; + } + } + { + int i = 4; + SAllocTraits::construct(s_alloc, &i, boost::container::default_init); + if(i != 4){ + return 1; + } + } { copymovable c; copymovable c2; diff --git a/test/deque_test.cpp b/test/deque_test.cpp index 2889423..f483fd6 100644 --- a/test/deque_test.cpp +++ b/test/deque_test.cpp @@ -332,6 +332,10 @@ int main () return 1; if(test::vector_test()) return 1; + if(!test::default_init_test< deque > >()){ + std::cerr << "Default init test failed" << std::endl; + return 1; + } } const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE); diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp index 459aace..6390d7e 100644 --- a/test/stable_vector_test.cpp +++ b/test/stable_vector_test.cpp @@ -66,6 +66,36 @@ void recursive_vector_test()//Test for recursive types } } +bool default_init_test()//Test for default initialization +{ + typedef stable_vector > svector_t; + + const std::size_t Capacity = 100; + + { + test::default_init_allocator::reset_pattern(0); + svector_t v(Capacity, default_init); + svector_t::iterator it = v.begin(); + //Compare with the pattern + for(std::size_t i = 0; i != Capacity; ++i, ++it){ + if(*it != static_cast(i)) + return false; + } + } + { + test::default_init_allocator::reset_pattern(100); + svector_t v; + v.resize(Capacity, default_init); + svector_t::iterator it = v.begin(); + //Compare with the pattern + for(std::size_t i = 0; i != Capacity; ++i, ++it){ + if(*it != static_cast(i+100)) + return false; + } + } + return true; +} + int main() { recursive_vector_test(); @@ -102,6 +132,11 @@ int main() if(test::vector_test()) return 1; + if(!test::default_init_test< stable_vector > >()){ + std::cerr << "Default init test failed" << std::endl; + return 1; + } + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE); if(!boost::container::test::test_emplace < stable_vector, Options>()) diff --git a/test/static_vector_test.cpp b/test/static_vector_test.cpp index 21efeb7..30914af 100644 --- a/test/static_vector_test.cpp +++ b/test/static_vector_test.cpp @@ -611,6 +611,53 @@ void test_sv_elem(T const& t) v.emplace_back(N/2, t); } +bool default_init_test()//Test for default initialization +{ + typedef static_vector di_vector_t; + + const std::size_t Capacity = 100; + + { + di_vector_t v; + int *p = v.data(); + + for(std::size_t i = 0; i != Capacity; ++i, ++p){ + *p = static_cast(i); + } + + //Destroy the vector, p stilll pointing to the storage + v.~di_vector_t(); + + di_vector_t &rv = *::new(&v)di_vector_t(Capacity, default_init); + di_vector_t::iterator it = rv.begin(); + + for(std::size_t i = 0; i != Capacity; ++i, ++it){ + if(*it != static_cast(i)) + return false; + } + + v.~di_vector_t(); + } + { + di_vector_t v; + + int *p = v.data(); + for(std::size_t i = 0; i != Capacity; ++i, ++p){ + *p = static_cast(i+100); + } + + v.resize(Capacity, default_init); + + di_vector_t::iterator it = v.begin(); + for(std::size_t i = 0; i != Capacity; ++i, ++it){ + if(*it != static_cast(i+100)) + return false; + } + } + + return true; +} + int main(int, char* []) { using boost::container::test::movable_and_copyable_int; @@ -727,6 +774,9 @@ int main(int, char* []) BOOST_TEST(counting_value::count() == 0); test_sv_elem(shptr_value(50)); test_sv_elem(movable_and_copyable_int(50)); + + BOOST_TEST(default_init_test() == true); + return boost::report_errors(); } diff --git a/test/vector_test.cpp b/test/vector_test.cpp index 3b34c92..80417c3 100644 --- a/test/vector_test.cpp +++ b/test/vector_test.cpp @@ -151,6 +151,10 @@ int main() return 1; if(test_expand_bwd()) return 1; + if(!test::default_init_test< vector > >()){ + std::cerr << "Default init test failed" << std::endl; + return 1; + } MyEnumVector v; Test t; diff --git a/test/vector_test.hpp b/test/vector_test.hpp index b1a4fb5..3dc2401 100644 --- a/test/vector_test.hpp +++ b/test/vector_test.hpp @@ -31,12 +31,130 @@ #include #include #include +#include #include "insert_test.hpp" namespace boost{ namespace container { namespace test{ +// +template +class default_init_allocator_base +{ + protected: + static unsigned char s_pattern; + static bool s_ascending; + + public: + static void reset_pattern(unsigned char value) + { s_pattern = value; } + + static void set_ascending(bool enable) + { s_ascending = enable; } +}; + +template +unsigned char default_init_allocator_base::s_pattern = 0u; + +template +bool default_init_allocator_base::s_ascending = true; + +template +class default_init_allocator + : public default_init_allocator_base<0> +{ + typedef default_init_allocator_base<0> base_t; + public: + typedef T value_type; + + default_init_allocator() + {} + + template + default_init_allocator(default_init_allocator) + {} + + T* allocate(std::size_t n) + { + //Initialize memory to a pattern + T *const p = ::new T[n]; + unsigned char *puc_raw = reinterpret_cast(p); + std::size_t max = sizeof(T)*n; + if(base_t::s_ascending){ + for(std::size_t i = 0; i != max; ++i){ + puc_raw[i] = static_cast(s_pattern++); + } + } + else{ + for(std::size_t i = 0; i != max; ++i){ + puc_raw[i] = static_cast(s_pattern--); + } + } + return p; + } + + void deallocate(T *p, std::size_t) + { delete[] p; } +}; + +template +inline bool check_ascending_byte_pattern(const T&t) +{ + const unsigned char *pch = &reinterpret_cast(t); + const std::size_t max = sizeof(T); + for(std::size_t i = 1; i != max; ++i){ + if( (pch[i-1] != ((unsigned char)(pch[i]-1u))) ){ + return false; + } + } + return true; +} + +template +inline bool check_descending_byte_pattern(const T&t) +{ + const unsigned char *pch = &reinterpret_cast(t); + const std::size_t max = sizeof(T); + for(std::size_t i = 1; i != max; ++i){ + if( (pch[i-1] != ((unsigned char)(pch[i]+1u))) ){ + return false; + } + } + return true; +} + +template +bool default_init_test()//Test for default initialization +{ + const std::size_t Capacity = 100; + + { + test::default_init_allocator::reset_pattern(0); + test::default_init_allocator::set_ascending(true); + IntDefaultInitAllocVector v(Capacity, default_init); + typename IntDefaultInitAllocVector::iterator it = v.begin(); + //Compare with the pattern + for(std::size_t i = 0; i != Capacity; ++i, ++it){ + if(!test::check_ascending_byte_pattern(*it)) + return false; + } + } + { + test::default_init_allocator::reset_pattern(100); + test::default_init_allocator::set_ascending(false); + IntDefaultInitAllocVector v; + v.resize(Capacity, default_init); + typename IntDefaultInitAllocVector::iterator it = v.begin(); + //Compare with the pattern + for(std::size_t i = 0; i != Capacity; ++i, ++it){ + if(!test::check_descending_byte_pattern(*it)) + return false; + } + } + return true; +} + template bool vector_copyable_only(V1 *, V2 *, boost::container::container_detail::false_type) { @@ -100,7 +218,7 @@ template int vector_test() { typedef std::vector MyStdVector; - typedef typename MyBoostVector::value_type IntType; + typedef typename MyBoostVector::value_type IntType; const int max = 100; if(!test_range_insertion()){ From 5b9b2c26dc1acaff86c8724ad756fbba4350d89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 29 Sep 2013 11:36:06 +0000 Subject: [PATCH 22/26] Implemented 2x grow factor for vector capacity [SVN r85996] --- include/boost/container/detail/utilities.hpp | 24 ++++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/include/boost/container/detail/utilities.hpp b/include/boost/container/detail/utilities.hpp index c42087c..8aa020a 100644 --- a/include/boost/container/detail/utilities.hpp +++ b/include/boost/container/detail/utilities.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -115,18 +116,21 @@ SizeType ,const SizeType capacity ,const SizeType n) { -// if (n > max_size - capacity) -// throw std::length_error("get_next_capacity"); + const SizeType remaining = max_size - capacity; + if ( remaining < n ) + boost::container::throw_length_error("get_next_capacity, allocator's max_size reached"); + const SizeType additional = max_value(n, capacity); + return ( remaining < additional ) ? max_size : ( capacity + additional ); + #if 0 //Alternative for 50% grow + const SizeType m3 = max_size/3; - const SizeType m3 = max_size/3; + if (capacity < m3) + return capacity + max_value(3*(capacity+1)/5, n); - 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; + if (capacity < m3*2) + return capacity + max_value((capacity+1)/2, n); + return max_size; + #endif } template From 3921e08520795caeacae9814048021d291400d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 29 Sep 2013 11:37:30 +0000 Subject: [PATCH 23/26] Tagged vector_alloc_holder constructors that allocate but don't initialize memory to improve maintainability. [SVN r85997] --- include/boost/container/stable_vector.hpp | 4 +-- include/boost/container/vector.hpp | 32 ++++++++++++----------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 7b31cc4..23b3d4b 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -123,8 +123,8 @@ struct node rebind_pointer::type > { -// private: -// node(); + private: + node(); public: typename ::boost::intrusive::pointer_traits::element_type value; diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index eabcab9..675ae12 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -224,6 +224,9 @@ namespace container_detail { #endif //#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER +struct uninitialized_size_t {}; +static const uninitialized_size_t uninitialized_size = uninitialized_size_t(); + template struct vector_value_traits { @@ -291,7 +294,7 @@ struct vector_alloc_holder //Constructor, does not throw template - explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a, size_type initial_size) + explicit vector_alloc_holder(uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size) : Allocator(boost::forward(a)) , m_start() , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this @@ -303,7 +306,7 @@ struct vector_alloc_holder } //Constructor, does not throw - explicit vector_alloc_holder(size_type initial_size) + explicit vector_alloc_holder(uninitialized_size_t, size_type initial_size) : Allocator() , m_start() , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this @@ -355,11 +358,8 @@ struct vector_alloc_holder size_type next_capacity(size_type additional_objects) const { - std::size_t num_objects = this->m_size + additional_objects; - std::size_t next_cap = this->m_capacity + this->m_capacity/2; - return num_objects > next_cap ? num_objects : next_cap;/* - return get_next_capacity( allocator_traits_type::max_size(this->m_holder.alloc()) - , this->m_capacity, additional_objects);*/ + return get_next_capacity( allocator_traits_type::max_size(this->alloc()) + , this->m_capacity, additional_objects); } pointer m_start; @@ -425,7 +425,7 @@ struct vector_alloc_holder - explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a, size_type initial_size) + vector_alloc_holder(uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size) : Allocator(boost::forward(a)) , m_size(initial_size) //Size is initialized here... { @@ -434,7 +434,7 @@ struct vector_alloc_holderComplexity: Linear to n. explicit vector(size_type n) - : m_holder(n) + : m_holder(container_detail::uninitialized_size, n) { boost::container::uninitialized_value_init_alloc_n (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); @@ -646,7 +646,7 @@ class vector //! //! Note: Non-standard extension explicit vector(size_type n, default_init_t) - : m_holder(n) + : m_holder(container_detail::uninitialized_size, n) { boost::container::uninitialized_default_init_alloc_n (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); @@ -660,7 +660,7 @@ class vector //! //! Complexity: Linear to n. vector(size_type n, const T& value) - : m_holder(n) + : m_holder(container_detail::uninitialized_size, n) { boost::container::uninitialized_fill_alloc_n (this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start())); @@ -674,7 +674,7 @@ class vector //! //! Complexity: Linear to n. vector(size_type n, const T& value, const allocator_type& a) - : m_holder(a, n) + : m_holder(container_detail::uninitialized_size, a, n) { boost::container::uninitialized_fill_alloc_n (this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start())); @@ -713,7 +713,9 @@ class vector //! //! Complexity: Linear to the elements x contains. vector(const vector &x) - : m_holder(allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc()), x.size()) + : m_holder( container_detail::uninitialized_size + , allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc()) + , x.size()) { ::boost::container::uninitialized_copy_alloc_n ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start()) @@ -754,7 +756,7 @@ class vector //! //! Complexity: Linear to the elements x contains. vector(const vector &x, const allocator_type &a) - : m_holder(a, x.size()) + : m_holder(container_detail::uninitialized_size, a, x.size()) { ::boost::container::uninitialized_copy_alloc_n_source ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start()) From 232e18956ac7475c7f9512b3953226819540167a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 29 Sep 2013 11:38:47 +0000 Subject: [PATCH 24/26] Fixed error for test_allocator::max_size(), now returns std::size_t(-1) [SVN r85998] --- test/scoped_allocator_adaptor_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/scoped_allocator_adaptor_test.cpp b/test/scoped_allocator_adaptor_test.cpp index 3464aa4..f535a54 100644 --- a/test/scoped_allocator_adaptor_test.cpp +++ b/test/scoped_allocator_adaptor_test.cpp @@ -68,7 +68,7 @@ class test_allocator } std::size_t max_size() const - { return std::size_t(Id); } + { return std::size_t(-1); } T* allocate(std::size_t n) { return (T*)::new char[n*sizeof(T)]; } From 59c5ed7781e192306cee37e009226771a479965d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 29 Sep 2013 11:39:34 +0000 Subject: [PATCH 25/26] Fixed error in default_init_allocator, it should not construct objects, only allocate raw memory. [SVN r85999] --- test/static_vector_test.cpp | 8 -------- test/vector_test.hpp | 10 +++++----- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/test/static_vector_test.cpp b/test/static_vector_test.cpp index 30914af..4521aef 100644 --- a/test/static_vector_test.cpp +++ b/test/static_vector_test.cpp @@ -11,14 +11,6 @@ #include #include -// TODO: Disable parts of the unit test that should not run when BOOST_NO_EXCEPTIONS -// if exceptions are enabled there must be a user defined throw_exception function -#ifdef BOOST_NO_EXCEPTIONS -namespace boost { - void throw_exception(std::exception const &){}; // user defined -} // namespace boost -#endif // BOOST_NO_EXCEPTIONS - #include #include diff --git a/test/vector_test.hpp b/test/vector_test.hpp index 3dc2401..0eb229b 100644 --- a/test/vector_test.hpp +++ b/test/vector_test.hpp @@ -78,9 +78,9 @@ class default_init_allocator T* allocate(std::size_t n) { //Initialize memory to a pattern - T *const p = ::new T[n]; - unsigned char *puc_raw = reinterpret_cast(p); - std::size_t max = sizeof(T)*n; + const std::size_t max = sizeof(T)*n; + unsigned char *puc_raw = ::new unsigned char[max]; + if(base_t::s_ascending){ for(std::size_t i = 0; i != max; ++i){ puc_raw[i] = static_cast(s_pattern++); @@ -91,11 +91,11 @@ class default_init_allocator puc_raw[i] = static_cast(s_pattern--); } } - return p; + return (T*)puc_raw;; } void deallocate(T *p, std::size_t) - { delete[] p; } + { delete[] (unsigned char*)p; } }; template From 62227ae74103ce162ea3f156ecf91eabbe6a5e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 30 Sep 2013 04:47:29 +0000 Subject: [PATCH 26/26] Fixed typo causing errors in clang builds. [SVN r86045] --- include/boost/container/detail/tree.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 2c3fdde..7400a1a 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -829,7 +829,7 @@ class rbtree template iterator emplace_hint_equal(const_iterator hint, Args&&... args) { - NodePtr p(AllocHolder::create_node(boost::forward(args)...)); + NodePtr tmp(AllocHolder::create_node(boost::forward(args)...)); scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); iterator ret(this->icont().insert_equal(hint.get(), *tmp)); destroy_deallocator.release();