From a8d20305dc808ad26a9819be0c613fcd3bdbf44c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 5 Sep 2012 09:28:24 +0000 Subject: [PATCH] Improved type safety and strict aliasing [SVN r80404] --- .../detail/multiallocation_chain.hpp | 23 +- include/boost/container/stable_vector.hpp | 498 +++++++++--------- include/boost/container/string.hpp | 364 +++++++------ test/check_equal_containers.hpp | 5 - 4 files changed, 467 insertions(+), 423 deletions(-) diff --git a/include/boost/container/detail/multiallocation_chain.hpp b/include/boost/container/detail/multiallocation_chain.hpp index c995253..e701643 100644 --- a/include/boost/container/detail/multiallocation_chain.hpp +++ b/include/boost/container/detail/multiallocation_chain.hpp @@ -157,18 +157,20 @@ class transform_multiallocation_chain MultiallocationChain holder_; typedef typename MultiallocationChain::void_pointer void_pointer; typedef typename boost::intrusive::pointer_traits - ::template rebind_pointer::type pointer; + void_pointer_traits; + typedef typename void_pointer_traits::template + rebind_pointer::type pointer; + typedef typename boost::intrusive::pointer_traits + pointer_traits; - static pointer cast(void_pointer p) - { - return pointer(static_cast(container_detail::to_raw_pointer(p))); - } + static pointer cast(const void_pointer &p) + { return pointer_traits::static_cast_from(p); } public: typedef transform_iterator < typename MultiallocationChain::iterator - , container_detail::cast_functor > iterator; - typedef typename MultiallocationChain::size_type size_type; + , container_detail::cast_functor > iterator; + typedef typename MultiallocationChain::size_type size_type; transform_multiallocation_chain() : holder_() @@ -234,8 +236,11 @@ class transform_multiallocation_chain static iterator iterator_to(pointer p) { return iterator(MultiallocationChain::iterator_to(p)); } - std::pair extract_data() - { return holder_.extract_data(); } + std::pair extract_data() + { + std::pair data(holder_.extract_data()); + return std::pair(cast(data.first), cast(data.second)); + } MultiallocationChain extract_multiallocation_chain() { diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index f43db03..30f1a4f 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -36,10 +36,11 @@ #include #include #include - -#include +#include +#include //max #include #include +#include //placement new ///@cond @@ -104,23 +105,44 @@ class clear_on_destroy bool do_clear_; }; -template -struct node_type_base -{ - node_type_base() - {} - void set_pointer(const VoidPtr &p) - { up = p; } +template +struct node; - VoidPtr up; +template +struct node_base +{ + private: + typedef NodePtr node_ptr; + typedef typename boost::intrusive:: + pointer_traits node_ptr_traits; + typedef typename node_ptr_traits:: + template rebind_pointer + ::type node_base_ptr; + typedef typename node_ptr_traits:: + template rebind_pointer + ::type node_ptr_ptr; + + public: + node_base(const node_ptr_ptr &n) + : up(n) + {} + + node_base() + : up() + {} + + node_ptr_ptr up; }; template -struct node_type - : public node_type_base +struct node + : public node_base + ::template + rebind_pointer< node >::type> { private: - node_type(); + node(); public: T value; @@ -135,90 +157,67 @@ class iterator , Pointer , Reference> { - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type void_ptr; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_void_ptr; - typedef node_type node_type_t; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type node_type_ptr_t; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_node_type_ptr_t; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type void_ptr_ptr; + typedef boost::intrusive:: + pointer_traits ptr_traits; + typedef typename ptr_traits::template + rebind_pointer::type void_ptr; + typedef node node_type; + typedef typename ptr_traits::template + rebind_pointer::type node_ptr; + typedef typename ptr_traits::template + rebind_pointer::type node_ptr_ptr; + typedef typename ptr_traits::template + rebind_pointer::type friend_iterator_pointer; - friend class iterator::template rebind_pointer::type>; + friend class iterator; public: typedef std::random_access_iterator_tag iterator_category; typedef T value_type; - typedef typename boost::intrusive:: - pointer_traits::difference_type difference_type; + typedef typename ptr_traits::difference_type difference_type; typedef Pointer pointer; typedef Reference reference; iterator() {} - explicit iterator(node_type_ptr_t pn) - : pn(pn) + explicit iterator(node_ptr p) + : pn(p) {} - iterator(const iterator::template rebind_pointer::type>& x) + iterator(const iterator& x) : pn(x.pn) {} - node_type_ptr_t node() const - { return pn; } - - private: - static node_type_ptr_t node_ptr_cast(const void_ptr &p) - { - return node_type_ptr_t(static_cast(container_detail::to_raw_pointer(p))); - } - - static const_node_type_ptr_t node_ptr_cast(const const_void_ptr &p) - { - return const_node_type_ptr_t(static_cast(container_detail::to_raw_pointer(p))); - } - - static void_ptr_ptr void_ptr_ptr_cast(const void_ptr &p) - { - return void_ptr_ptr(static_cast(container_detail::to_raw_pointer(p))); - } - - reference dereference() const - { return pn->value; } - bool equal(const iterator& x) const - { return pn==x.pn; } - void increment() - { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+1)); } - void decrement() - { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)-1)); } - void advance(difference_type n) - { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+n)); } - difference_type distance_to(const iterator& x)const - { return void_ptr_ptr_cast(x.pn->up) - void_ptr_ptr_cast(pn->up); } - public: //Pointer like operators - reference operator*() const { return this->dereference(); } - pointer operator->() const { return pointer(&this->dereference()); } + reference operator*() const + { return pn->value; } + + pointer operator->() const + { return ptr_traits::pointer_to(*this); } //Increment / Decrement iterator& operator++() - { this->increment(); return *this; } + { + if(node_ptr_ptr p = this->pn->up){ + ++p; + this->pn = *p; + } + return *this; + } iterator operator++(int) { iterator tmp(*this); ++*this; return iterator(tmp); } iterator& operator--() - { this->decrement(); return *this; } + { + if(node_ptr_ptr p = this->pn->up){ + --p; + this->pn = *p; + } + return *this; + } iterator operator--(int) { iterator tmp(*this); --*this; return iterator(tmp); } @@ -232,7 +231,10 @@ class iterator iterator& operator+=(difference_type off) { - pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+off)); + if(node_ptr_ptr p = this->pn->up){ + p += off; + this->pn = *p; + } return *this; } @@ -262,7 +264,7 @@ class iterator friend difference_type operator-(const iterator& left, const iterator& right) { - return void_ptr_ptr_cast(left.pn->up) - void_ptr_ptr_cast(right.pn->up); + return left.pn->up - right.pn->up; } //Comparison operators @@ -273,18 +275,18 @@ class iterator { return l.pn != r.pn; } friend bool operator< (const iterator& l, const iterator& r) - { return void_ptr_ptr_cast(l.pn->up) < void_ptr_ptr_cast(r.pn->up); } + { return l.pn->up < r.pn->up; } friend bool operator<= (const iterator& l, const iterator& r) - { return void_ptr_ptr_cast(l.pn->up) <= void_ptr_ptr_cast(r.pn->up); } + { return l.pn->up <= r.pn->up; } friend bool operator> (const iterator& l, const iterator& r) - { return void_ptr_ptr_cast(l.pn->up) > void_ptr_ptr_cast(r.pn->up); } + { return l.pn->up > r.pn->up; } friend bool operator>= (const iterator& l, const iterator& r) - { return void_ptr_ptr_cast(l.pn->up) >= void_ptr_ptr_cast(r.pn->up); } + { return l.pn->up >= r.pn->up; } - node_type_ptr_t pn; + node_ptr pn; }; template @@ -368,34 +370,32 @@ class stable_vector typedef allocator_traits allocator_traits_type; typedef typename container_detail:: move_const_ref_type::type insert_const_ref_type; + typedef boost::intrusive:: + pointer_traits + ptr_traits; typedef typename boost::intrusive::pointer_traits :: template rebind_pointer::type void_ptr; - typedef typename boost::intrusive::pointer_traits - ::template - rebind_pointer::type const_void_ptr; - typedef typename boost::intrusive::pointer_traits - ::template - rebind_pointer::type void_ptr_ptr; - typedef typename boost::intrusive::pointer_traits - ::template - rebind_pointer::type const_void_ptr_ptr; - typedef stable_vector_detail::node_type - node_type_t; - typedef typename boost::intrusive::pointer_traits - ::template - rebind_pointer::type node_type_ptr_t; - typedef stable_vector_detail::node_type_base - node_type_base_t; - typedef typename boost::intrusive::pointer_traits - ::template - rebind_pointer::type node_type_base_ptr_t; - typedef ::boost::container::vector node_type; + typedef typename ptr_traits::template + rebind_pointer::type node_ptr; + typedef typename ptr_traits::template + rebind_pointer::type node_ptr_ptr; + typedef stable_vector_detail:: + node_base node_base_type; + typedef typename ptr_traits::template + rebind_pointer::type node_base_ptr; + typedef boost::intrusive:: + pointer_traits node_base_ptr_traits; + typedef boost::intrusive:: + pointer_traits node_ptr_traits; + typedef boost::intrusive:: + pointer_traits node_ptr_ptr_traits; + typedef ::boost::container::vector::type> impl_type; + ::type> impl_type; typedef typename impl_type::iterator impl_iterator; - typedef typename impl_type::const_iterator const_impl_iterator; typedef ::boost::container::container_detail:: integral_constant allocator_v1; @@ -406,37 +406,37 @@ class stable_vector version::value> alloc_version; typedef typename allocator_traits_type:: template portable_rebind_alloc - ::type node_allocator_type; + ::type node_allocator_type; - node_type_ptr_t allocate_one() + node_ptr allocate_one() { return this->allocate_one(alloc_version()); } template - node_type_ptr_t allocate_one(AllocatorVersion, + node_ptr allocate_one(AllocatorVersion, typename boost::container::container_detail::enable_if_c ::value>::type * = 0) { return this->priv_node_alloc().allocate(1); } template - node_type_ptr_t allocate_one(AllocatorVersion, + node_ptr allocate_one(AllocatorVersion, typename boost::container::container_detail::enable_if_c ::value>::type * = 0) { return this->priv_node_alloc().allocate_one(); } - void deallocate_one(node_type_ptr_t p) + void deallocate_one(node_ptr p) { return this->deallocate_one(p, alloc_version()); } template - void deallocate_one(node_type_ptr_t p, AllocatorVersion, + void deallocate_one(node_ptr p, AllocatorVersion, typename boost::container::container_detail::enable_if_c ::value>::type * = 0) { this->priv_node_alloc().deallocate(p, 1); } template - void deallocate_one(node_type_ptr_t p, AllocatorVersion, + void deallocate_one(node_ptr p, AllocatorVersion, typename boost::container::container_detail::enable_if_c ::value>::type * = 0) @@ -469,11 +469,11 @@ class stable_vector private: BOOST_COPYABLE_AND_MOVABLE(stable_vector) static const size_type ExtraPointers = 3; - //This container stores metadata at the end of the void_ptr vector with additional 3 pointers: - // back() is impl.back() - ExtraPointers; - // end node index is impl.end()[-3] - // Node cache first is impl.end()[-2]; - // Node cache last is *impl.back(); + //This container stores metadata at the end of the node_ptr vector with additional 3 pointers: + // back() is this->impl.back() - ExtraPointers; + // end node index is *(this->impl.end() -3) + // Node cache first is *(this->impl.end() - 2); + // Node cache last is this->impl.back(); typedef typename stable_vector_detail:: select_multiallocation_chain @@ -681,7 +681,6 @@ class stable_vector } //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())); } @@ -757,14 +756,13 @@ class stable_vector stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT { return this->priv_node_alloc(); } - //! Effects: Returns an iterator to the first element contained in the stable_vector. //! //! Throws: Nothing. //! //! Complexity: Constant. iterator begin() - { return (impl.empty()) ? end(): iterator(node_ptr_cast(impl.front())) ; } + { return (this->impl.empty()) ? this->end(): iterator(this->impl.front()) ; } //! Effects: Returns a const_iterator to the first element contained in the stable_vector. //! @@ -772,21 +770,21 @@ class stable_vector //! //! Complexity: Constant. const_iterator begin()const - { return (impl.empty()) ? cend() : const_iterator(node_ptr_cast(impl.front())) ; } + { return (this->impl.empty()) ? this->cend() : const_iterator(this->impl.front()) ; } //! Effects: Returns an iterator to the end of the stable_vector. //! //! Throws: Nothing. //! //! Complexity: Constant. - iterator end() {return iterator(get_end_node());} + iterator end() {return iterator(this->get_end_node());} //! Effects: Returns a const_iterator to the end of the stable_vector. //! //! Throws: Nothing. //! //! Complexity: Constant. - const_iterator end()const {return const_iterator(get_end_node());} + const_iterator end()const {return const_iterator(this->get_end_node());} //! Effects: Returns a reverse_iterator pointing to the beginning //! of the reversed stable_vector. @@ -856,7 +854,7 @@ class stable_vector //! //! Complexity: Constant. size_type size() const - { return impl.empty() ? 0 : (impl.size() - ExtraPointers); } + { return this->impl.empty() ? 0 : (this->impl.size() - ExtraPointers); } //! Effects: Returns the largest possible size of the stable_vector. //! @@ -864,7 +862,7 @@ class stable_vector //! //! Complexity: Constant. size_type max_size() const - { return impl.max_size() - ExtraPointers; } + { return this->impl.max_size() - ExtraPointers; } //! Effects: Number of elements for which memory has been allocated. //! capacity() is always greater than or equal to size(). @@ -874,7 +872,7 @@ class stable_vector //! Complexity: Constant. size_type capacity() const { - if(!impl.capacity()){ + if(!this->impl.capacity()){ return 0; } else{ @@ -890,7 +888,7 @@ class stable_vector //! //! Complexity: Constant. bool empty() const - { return impl.empty() || impl.size() == ExtraPointers; } + { return this->impl.empty() || this->impl.size() == ExtraPointers; } //! Effects: Inserts or erases elements at the end such that //! the size becomes n. New elements are copy constructed from x. @@ -901,7 +899,7 @@ class stable_vector void resize(size_type n, const T& t) { STABLE_VECTOR_CHECK_INVARIANT; - if(n > size()) + if(n > this->size()) this->insert(this->cend(), n - this->size(), t); else if(n < this->size()) this->erase(this->cbegin() + n, this->cend()); @@ -917,7 +915,7 @@ class stable_vector { typedef default_construct_iterator default_iterator; STABLE_VECTOR_CHECK_INVARIANT; - if(n > size()) + if(n > this->size()) this->insert(this->cend(), default_iterator(n - this->size()), default_iterator()); else if(n < this->size()) this->erase(this->cbegin() + n, this->cend()); @@ -940,11 +938,11 @@ class stable_vector if(n > old_capacity){ this->initialize_end_node(n); const void * old_ptr = &impl[0]; - impl.reserve(n + ExtraPointers); + this->impl.reserve(n + ExtraPointers); bool realloced = &impl[0] != old_ptr; //Fix the pointers for the newly allocated buffer if(realloced){ - this->align_nodes(impl.begin(), impl.begin()+size+1); + this->align_nodes(this->impl.begin(), this->impl.begin()+size+1); } //Now fill pool if data is not enough if((n - size) > this->internal_data.pool_size){ @@ -961,7 +959,8 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - reference operator[](size_type n){return value(impl[n]);} + reference operator[](size_type n) + { return this->impl[n]->value; } //! Requires: size() > n. //! @@ -971,7 +970,8 @@ class stable_vector //! Throws: Nothing. //! //! Complexity: Constant. - const_reference operator[](size_type n)const{return value(impl[n]);} + const_reference operator[](size_type n)const + { return this->impl[n]->value; } //! Requires: size() > n. //! @@ -983,7 +983,7 @@ class stable_vector //! Complexity: Constant. reference at(size_type n) { - if(n>=size()) + if(n>=this->size()) throw std::out_of_range("invalid subscript at stable_vector::at"); return operator[](n); } @@ -998,7 +998,7 @@ class stable_vector //! Complexity: Constant. const_reference at(size_type n)const { - if(n>=size()) + if(n>=this->size()) throw std::out_of_range("invalid subscript at stable_vector::at"); return operator[](n); } @@ -1012,7 +1012,7 @@ class stable_vector //! //! Complexity: Constant. reference front() - { return value(impl.front()); } + { return this->impl.front()->value; } //! Requires: !empty() //! @@ -1023,7 +1023,7 @@ class stable_vector //! //! Complexity: Constant. const_reference front()const - { return value(impl.front()); } + { return this->impl.front()->value; } //! Requires: !empty() //! @@ -1034,7 +1034,7 @@ class stable_vector //! //! Complexity: Constant. reference back() - { return value(*(&impl.back() - ExtraPointers)); } + { return (*(&this->impl.back() - ExtraPointers))->value; } //! Requires: !empty() //! @@ -1045,7 +1045,7 @@ class stable_vector //! //! Complexity: Constant. const_reference back()const - { return value(*(&impl.back() - ExtraPointers)); } + { return (*(&this->impl.back() - ExtraPointers))->value; } //! Effects: Inserts a copy of x at the end of the stable_vector. //! @@ -1183,10 +1183,10 @@ class stable_vector difference_type d = position - this->cbegin(); if(n){ this->insert_iter_prolog(n, d); - const impl_iterator it(impl.begin() + d); + const impl_iterator it(this->impl.begin() + d); this->priv_insert_iter_fwd(it, first, last, n); //Fix the pointers for the newly allocated buffer - this->align_nodes(it + n, get_last_align()); + this->align_nodes(it + n, this->get_end_align()); } return this->begin() + d; } @@ -1277,10 +1277,10 @@ class stable_vector { STABLE_VECTOR_CHECK_INVARIANT; difference_type d = position - this->cbegin(); - impl_iterator it = impl.begin() + d; + impl_iterator it = this->impl.begin() + d; this->delete_node(*it); - it = impl.erase(it); - this->align_nodes(it, get_last_align()); + it = this->impl.erase(it); + this->align_nodes(it, this->get_end_align()); return this->begin()+d; } @@ -1295,11 +1295,11 @@ class stable_vector STABLE_VECTOR_CHECK_INVARIANT; difference_type d1 = first - this->cbegin(), d2 = last - this->cbegin(); if(d1 != d2){ - impl_iterator it1(impl.begin() + d1), it2(impl.begin() + d2); + impl_iterator it1(this->impl.begin() + d1), it2(this->impl.begin() + d2); for(impl_iterator it = it1; it != it2; ++it) this->delete_node(*it); - impl_iterator e = impl.erase(it1, it2); - this->align_nodes(e, get_last_align()); + impl_iterator e = this->impl.erase(it1, it2); + this->align_nodes(e, this->get_end_align()); } return iterator(this->begin() + d1); } @@ -1342,7 +1342,7 @@ class stable_vector if(this->empty()){ this->impl.clear(); this->impl.shrink_to_fit(); - this->internal_data.set_end_pointer_to_default_constructed(); + this->internal_data.end_node.up = node_ptr_ptr(); } //Otherwise, try to shrink-to-fit the index and readjust pointers if necessary else{ @@ -1352,7 +1352,7 @@ class stable_vector bool realloced = &impl[0] != old_ptr; //Fix the pointers for the newly allocated buffer if(realloced){ - this->align_nodes(impl.begin(), impl.begin()+size+1); + this->align_nodes(this->impl.begin(), this->impl.begin()+size+1); } } } @@ -1375,14 +1375,14 @@ class stable_vector ::value>::type * = 0) { - if(!impl.empty() && impl.back()){ - void_ptr &pool_first_ref = impl.end()[-2]; - void_ptr &pool_last_ref = impl.back(); + if(!this->impl.empty() && this->impl.back()){ + node_ptr &pool_first_ref = *(this->impl.end() - 2); + node_ptr &pool_last_ref = this->impl.back(); multiallocation_chain holder; holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, this->internal_data.pool_size); while(!holder.empty()){ - node_type_ptr_t n = holder.front(); + node_ptr n = holder.front(); holder.pop_front(); this->deallocate_one(n); } @@ -1397,9 +1397,9 @@ class stable_vector ::value>::type * = 0) { - if(!impl.empty() && impl.back()){ - void_ptr &pool_first_ref = impl.end()[-2]; - void_ptr &pool_last_ref = impl.back(); + if(!this->impl.empty() && this->impl.back()){ + node_ptr &pool_first_ref = *(this->impl.end() - 2); + node_ptr &pool_last_ref = this->impl.back(); multiallocation_chain holder; holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size); this->priv_node_alloc().deallocate_individual(boost::move(holder)); @@ -1436,50 +1436,50 @@ class stable_vector ::value>::type * = 0) { - void_ptr &pool_first_ref = impl.end()[-2]; - void_ptr &pool_last_ref = impl.back(); + node_ptr &pool_first_ref = *(this->impl.end() - 2); + node_ptr &pool_last_ref = this->impl.back(); multiallocation_chain holder; holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size); //BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled::value == true)); multiallocation_chain m (this->priv_node_alloc().allocate_individual(n)); holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n); this->internal_data.pool_size += n; - std::pair data(holder.extract_data()); + std::pair data(holder.extract_data()); pool_first_ref = data.first; pool_last_ref = data.second; } - void put_in_pool(node_type_ptr_t p) + void put_in_pool(node_ptr p) { - void_ptr &pool_first_ref = impl.end()[-2]; - void_ptr &pool_last_ref = impl.back(); + node_ptr &pool_first_ref = *(this->impl.end()-2); + node_ptr &pool_last_ref = this->impl.back(); multiallocation_chain holder; holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size); holder.push_front(p); ++this->internal_data.pool_size; - std::pair ret(holder.extract_data()); + std::pair ret(holder.extract_data()); pool_first_ref = ret.first; pool_last_ref = ret.second; } - node_type_ptr_t priv_get_from_pool() + node_ptr priv_get_from_pool() { - if(!impl.back()){ - return node_type_ptr_t(0); + if(!this->impl.back()){ + return node_ptr(0); } else{ - void_ptr &pool_first_ref = impl.end()[-2]; - void_ptr &pool_last_ref = impl.back(); + node_ptr &pool_first_ref = *(this->impl.end() - 2); + node_ptr &pool_last_ref = this->impl.back(); multiallocation_chain holder; holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size); - node_type_ptr_t ret = holder.front(); + node_ptr ret = holder.front(); holder.pop_front(); --this->internal_data.pool_size; if(!internal_data.pool_size){ - pool_first_ref = pool_last_ref = void_ptr(0); + pool_first_ref = pool_last_ref = node_ptr(); } else{ - std::pair data(holder.extract_data()); + std::pair data(holder.extract_data()); pool_first_ref = data.first; pool_last_ref = data.second; } @@ -1491,79 +1491,62 @@ class stable_vector { initialize_end_node(n); const void* old_ptr = &impl[0]; - //size_type old_capacity = capacity(); - //size_type old_size = size(); - impl.insert(impl.begin()+d, n, 0); + //size_type old_capacity = this->capacity(); + //size_type old_size = this->size(); + this->impl.insert(this->impl.begin()+d, n, 0); bool realloced = &impl[0] != old_ptr; //Fix the pointers for the newly allocated buffer if(realloced){ - align_nodes(impl.begin(), impl.begin()+d); + align_nodes(this->impl.begin(), this->impl.begin()+d); } } - impl_iterator get_last_align() + impl_iterator get_end_align() { - return impl.end() - (ExtraPointers - 1); + return this->impl.end() - (ExtraPointers - 1); } - const_impl_iterator get_last_align() const - { - return impl.cend() - (ExtraPointers - 1); - } + static node_ptr_ptr ptr_to_node_ptr(node_ptr &n) + { return node_ptr_ptr_traits::pointer_to(n); } - static node_type_ptr_t node_ptr_cast(const void_ptr &p) + void initialize_end_node(const size_type impl_capacity = 0) { - return node_type_ptr_t(static_cast(container_detail::to_raw_pointer(p))); - } - - static node_type_base_ptr_t node_base_ptr_cast(const void_ptr &p) - { - return node_type_base_ptr_t(static_cast(container_detail::to_raw_pointer(p))); - } - - static value_type& value(const void_ptr &p) - { - return node_ptr_cast(p)->value; - } - - void initialize_end_node(size_type impl_capacity = 0) - { - if(impl.empty()){ - impl.reserve(impl_capacity + ExtraPointers); - impl.resize (ExtraPointers, void_ptr(0)); - impl[0] = &this->internal_data.end_node; - this->internal_data.end_node.up = &impl[0]; + if(this->impl.empty()){ + this->impl.reserve(impl_capacity + ExtraPointers); + this->impl.resize(ExtraPointers); + node_ptr &end_node_ref = impl[0]; + end_node_ref = this->get_end_node(); + this->internal_data.end_node.up = stable_vector::ptr_to_node_ptr(end_node_ref); } } void readjust_end_node() { if(!this->impl.empty()){ - void_ptr &end_node_ref = *(this->get_last_align()-1); + node_ptr &end_node_ref = *(this->get_end_align()-1); end_node_ref = this->get_end_node(); - this->internal_data.end_node.up = &end_node_ref; + this->internal_data.end_node.up = node_ptr_ptr_traits::pointer_to(end_node_ref); } else{ - this->internal_data.end_node.up = void_ptr(&this->internal_data.end_node.up); + this->internal_data.end_node.up = node_ptr_ptr(); } } - node_type_ptr_t get_end_node() const + node_ptr get_end_node() const { - const node_type_base_t* cp = &this->internal_data.end_node; - node_type_base_t* p = const_cast(cp); - return node_ptr_cast(p); + return node_ptr_traits::static_cast_from + (node_base_ptr_traits::pointer_to(const_cast(this->internal_data.end_node))); } template - void_ptr new_node(const void_ptr &up, Iter it) + node_ptr new_node(const node_ptr_ptr &up, Iter it) { - node_type_ptr_t p = this->allocate_one(); + node_ptr p = this->allocate_one(); try{ boost::container::construct_in_place(this->priv_node_alloc(), container_detail::addressof(p->value), it); //This does not throw - ::new(static_cast(container_detail::to_raw_pointer(p))) node_type_base_t; - p->set_pointer(up); + ::new(static_cast(container_detail::to_raw_pointer(p))) node_base_type; + p->up = up; } catch(...){ this->deallocate_one(p); @@ -1572,18 +1555,18 @@ class stable_vector return p; } - void delete_node(const void_ptr &p) + void delete_node(const node_ptr &n) { - node_type_ptr_t n(node_ptr_cast(p)); allocator_traits:: destroy(this->priv_node_alloc(), container_detail::to_raw_pointer(n)); + static_cast(container_detail::to_raw_pointer(n))->~node_base_type(); this->put_in_pool(n); } static void align_nodes(impl_iterator first, impl_iterator last) { while(first!=last){ - node_ptr_cast(*first)->up = void_ptr(&*first); + (*first)->up = stable_vector::ptr_to_node_ptr(*first); ++first; } } @@ -1594,14 +1577,14 @@ class stable_vector size_type i=0; try{ while(first!=last){ - it[i] = this->new_node(void_ptr_ptr(&it[i]), first); + it[i] = this->new_node(stable_vector::ptr_to_node_ptr(it[i]), first); ++first; ++i; } } catch(...){ - impl_iterator e = impl.erase(it + i, it + n); - this->align_nodes(e, get_last_align()); + impl_iterator e = this->impl.erase(it + i, it + n); + this->align_nodes(e, this->get_end_align()); throw; } } @@ -1612,7 +1595,7 @@ class stable_vector multiallocation_chain mem(this->priv_node_alloc().allocate_individual(n)); size_type i = 0; - node_type_ptr_t p = 0; + node_ptr p = 0; try{ while(first != last){ p = mem.front(); @@ -1620,8 +1603,8 @@ class stable_vector //This can throw boost::container::construct_in_place(this->priv_node_alloc(), container_detail::addressof(p->value), first); //This does not throw - ::new(static_cast(container_detail::to_raw_pointer(p))) node_type_base_t; - p->set_pointer(void_ptr_ptr(&it[i])); + ::new(static_cast(container_detail::to_raw_pointer(p))) node_base_type; + p->up = stable_vector::ptr_to_node_ptr(it[i]); ++first; it[i] = p; ++i; @@ -1630,8 +1613,8 @@ class stable_vector catch(...){ this->priv_node_alloc().deallocate_one(p); this->priv_node_alloc().deallocate_many(boost::move(mem)); - impl_iterator e = impl.erase(it+i, it+n); - this->align_nodes(e, get_last_align()); + impl_iterator e = this->impl.erase(it+i, it+n); + this->align_nodes(e, this->get_end_align()); throw; } } @@ -1640,7 +1623,7 @@ class stable_vector void priv_insert_iter_fwd(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n) { size_type i = 0; - node_type_ptr_t p = 0; + node_ptr p = 0; try{ while(first != last){ p = this->priv_get_from_pool(); @@ -1651,8 +1634,8 @@ class stable_vector //This can throw boost::container::construct_in_place(this->priv_node_alloc(), container_detail::addressof(p->value), first); //This does not throw - ::new(static_cast(container_detail::to_raw_pointer(p))) node_type_base_t; - p->set_pointer(void_ptr_ptr(&it[i])); + ::new(static_cast(container_detail::to_raw_pointer(p))) node_base_type; + p->up = stable_vector::ptr_to_node_ptr(it[i]); ++first; it[i]=p; ++i; @@ -1660,8 +1643,8 @@ class stable_vector } catch(...){ put_in_pool(p); - impl_iterator e = impl.erase(it+i, it+n); - this->align_nodes(e, get_last_align()); + impl_iterator e = this->impl.erase(it+i, it+n); + this->align_nodes(e, this->get_end_align()); throw; } } @@ -1676,23 +1659,32 @@ class stable_vector #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING) bool priv_invariant()const { - if(impl.empty()) - return !capacity() && !size(); - if(get_end_node() != *(impl.end() - ExtraPointers)){ + impl_type & impl_ref = const_cast(this->impl); + + if(impl_ref.empty()) + return !this->capacity() && !this->size(); + if(this->get_end_node() != *(impl_ref.end() - ExtraPointers)){ return false; } - for(const_impl_iterator it = impl.begin(), it_end = get_last_align(); it != it_end; ++it){ - if(const_void_ptr(node_ptr_cast(*it)->up) != - const_void_ptr(const_void_ptr_ptr(&*it))) + for( impl_iterator it = impl_ref.begin() + , it_end = const_cast(*this).get_end_align() + ; it != it_end + ; ++it){ + if((*it)->up != stable_vector::ptr_to_node_ptr(*it)){ return false; + } } - size_type n = capacity()-size(); - const void_ptr &pool_head = impl.back(); + + size_type n = this->capacity() - this->size(); + node_ptr &pool_first_ref = *(impl_ref.end() - 2); + node_ptr &pool_last_ref = impl_ref.back(); + multiallocation_chain holder; + holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size); + multiallocation_chain::iterator beg(holder.begin()), end(holder.end()); size_type num_pool = 0; - node_type_ptr_t p = node_ptr_cast(pool_head); - while(p){ + while(beg != end){ ++num_pool; - p = node_ptr_cast(p->up); + ++beg; } return n >= num_pool; } @@ -1722,25 +1714,16 @@ class stable_vector : node_allocator_type(boost::forward(a)) , pool_size(0) , end_node() - { - this->set_end_pointer_to_default_constructed(); - } + {} ebo_holder() : node_allocator_type() , pool_size(0) , end_node() - { - this->set_end_pointer_to_default_constructed(); - } - - void set_end_pointer_to_default_constructed() - { - end_node.set_pointer(void_ptr(&end_node.up)); - } + {} size_type pool_size; - node_type_base_t end_node; + node_base_type end_node; } internal_data; node_allocator_type &priv_node_alloc() { return internal_data; } @@ -1805,3 +1788,24 @@ void swap(stable_vector& x,stable_vector& y) #include #endif //BOOST_CONTAINER_STABLE_VECTOR_HPP + + + + + + + + + + + + + + + + + + + + + diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index ff1f8fd..4af2ae2 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -92,10 +93,11 @@ class basic_string_base public: typedef A allocator_type; //! The stored allocator type - typedef allocator_type stored_allocator_type; + typedef allocator_type stored_allocator_type; typedef typename allocator_traits_type::pointer pointer; typedef typename allocator_traits_type::value_type value_type; typedef typename allocator_traits_type::size_type size_type; + typedef ::boost::intrusive::pointer_traits pointer_traits; basic_string_base() : members_() @@ -123,10 +125,7 @@ class basic_string_base { if(!this->is_short()){ this->deallocate_block(); - allocator_traits_type::destroy - ( this->alloc() - , static_cast(static_cast(&this->members_.m_repr.r)) - ); + this->is_short(true); } } @@ -198,11 +197,17 @@ class basic_string_base long_raw_t r; short_t s; - short_t &short_repr() const - { return *const_cast(&s); } + const short_t &short_repr() const + { return s; } - long_t &long_repr() const - { return *const_cast(reinterpret_cast(&r)); } + const long_t &long_repr() const + { return *static_cast(static_cast(&r)); } + + short_t &short_repr() + { return s; } + + long_t &long_repr() + { return *static_cast(static_cast(&r)); } }; struct members_holder @@ -237,20 +242,22 @@ class basic_string_base { return static_cast(this->members_.m_repr.s.h.is_short != 0); } void is_short(bool yes) - { - if(yes && !this->is_short()){ + { + const bool was_short = this->is_short(); + if(yes && !was_short){ allocator_traits_type::destroy ( this->alloc() , static_cast(static_cast(&this->members_.m_repr.r)) ); + this->members_.m_repr.s.h.is_short = true; } - else{ + else if(!yes && was_short){ allocator_traits_type::construct ( this->alloc() , static_cast(static_cast(&this->members_.m_repr.r)) ); + this->members_.m_repr.s.h.is_short = false; } - this->members_.m_repr.s.h.is_short = yes; } private: @@ -274,7 +281,7 @@ class basic_string_base size_type &received_size, pointer reuse = 0) { if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){ - reuse = pointer(0); + reuse = pointer(); command &= ~(expand_fwd | expand_bwd); } return this->allocation_command @@ -292,7 +299,7 @@ class basic_string_base (void)limit_size; (void)reuse; if(!(command & allocate_new)) - return std::pair(pointer(0), false); + return std::pair(pointer(), false); received_size = preferred_size; return std::make_pair(this->alloc().allocate(received_size), false); } @@ -353,7 +360,7 @@ class basic_string_base pointer p = this->allocation_command(allocate_new, n, new_cap, new_cap).first; this->is_short(false); this->priv_long_addr(p); - this->priv_size(0); + this->priv_long_size(0); this->priv_storage(new_cap); } } @@ -379,13 +386,26 @@ class basic_string_base { return this->priv_storage() - 1; } pointer priv_short_addr() const - { return pointer(&this->members_.m_repr.short_repr().data[0]); } + { return pointer_traits::pointer_to(const_cast(this->members_.m_repr.short_repr().data[0])); } pointer priv_long_addr() const { return this->members_.m_repr.long_repr().start; } pointer priv_addr() const - { return this->is_short() ? pointer(&this->members_.m_repr.short_repr().data[0]) : this->members_.m_repr.long_repr().start; } + { + return this->is_short() + ? priv_short_addr() + : priv_long_addr() + ; + } + + pointer priv_end_addr() const + { + return this->is_short() + ? this->priv_short_addr() + this->priv_short_size() + : this->priv_long_addr() + this->priv_long_size() + ; + } void priv_long_addr(pointer addr) { this->members_.m_repr.long_repr().start = addr; } @@ -411,7 +431,7 @@ class basic_string_base } size_type priv_size() const - { return this->is_short() ? priv_short_size() : priv_long_size(); } + { return this->is_short() ? this->priv_short_size() : this->priv_long_size(); } size_type priv_short_size() const { return this->members_.m_repr.short_repr().h.length; } @@ -434,7 +454,7 @@ class basic_string_base void priv_long_size(size_type sz) { - this->members_.m_repr.long_repr().length = static_cast(sz); + this->members_.m_repr.long_repr().length = sz; } void swap_data(basic_string_base& other) @@ -444,16 +464,22 @@ class basic_string_base container_detail::do_swap(this->members_.m_repr, other.members_.m_repr); } else{ - repr_t copied(this->members_.m_repr); - this->members_.m_repr.long_repr() = other.members_.m_repr.long_repr(); - other.members_.m_repr = copied; + short_t short_backup(this->members_.m_repr.short_repr()); + long_t long_backup (other.members_.m_repr.long_repr()); + other.members_.m_repr.long_repr().~long_t(); + ::new(&this->members_.m_repr.long_repr()) long_t; + this->members_.m_repr.long_repr() = long_backup; + other.members_.m_repr.short_repr() = short_backup; } } else{ if(other.is_short()){ - repr_t copied(other.members_.m_repr); - other.members_.m_repr.long_repr() = this->members_.m_repr.long_repr(); - this->members_.m_repr = copied; + short_t short_backup(other.members_.m_repr.short_repr()); + long_t long_backup (this->members_.m_repr.long_repr()); + this->members_.m_repr.long_repr().~long_t(); + ::new(&other.members_.m_repr.long_repr()) long_t; + other.members_.m_repr.long_repr() = long_backup; + this->members_.m_repr.short_repr() = short_backup; } else{ container_detail::do_swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr()); @@ -581,6 +607,7 @@ class basic_string typedef typename base_t::allocator_v1 allocator_v1; typedef typename base_t::allocator_v2 allocator_v2; typedef typename base_t::alloc_version alloc_version; + typedef ::boost::intrusive::pointer_traits pointer_traits; /// @endcond public: // Constructor, destructor, assignment. @@ -742,8 +769,8 @@ class basic_string if(!this->is_short()){ this->deallocate_block(); this->is_short(true); - Traits::assign(*this->priv_addr(), this->priv_null()); - this->priv_size(0); + Traits::assign(*this->priv_addr(), CharT(0)); + this->priv_short_size(0); } } container_detail::assign_alloc(this->alloc(), x.alloc(), flag); @@ -818,7 +845,7 @@ class basic_string //! //! Complexity: Constant. iterator end() - { return this->priv_addr() + this->priv_size(); } + { return this->priv_end_addr(); } //! Effects: Returns a const_iterator to the end of the vector. //! @@ -826,7 +853,7 @@ class basic_string //! //! Complexity: Constant. const_iterator end() const - { return this->priv_addr() + this->priv_size(); } + { return this->priv_end_addr(); } //! Effects: Returns a const_iterator to the end of the vector. //! @@ -834,7 +861,7 @@ class basic_string //! //! Complexity: Constant. const_iterator cend() const - { return this->priv_addr() + this->priv_size(); } + { return this->priv_end_addr(); } //! Effects: Returns a reverse_iterator pointing to the beginning //! of the reversed vector. @@ -843,7 +870,7 @@ class basic_string //! //! Complexity: Constant. reverse_iterator rbegin() - { return reverse_iterator(this->priv_addr() + this->priv_size()); } + { return reverse_iterator(this->priv_end_addr()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning //! of the reversed vector. @@ -861,7 +888,7 @@ class basic_string //! //! Complexity: Constant. const_reverse_iterator crbegin() const - { return const_reverse_iterator(this->priv_addr() + this->priv_size()); } + { return const_reverse_iterator(this->priv_end_addr()); } //! Effects: Returns a reverse_iterator pointing to the end //! of the reversed vector. @@ -950,7 +977,7 @@ class basic_string //! Complexity: Linear to the difference between size() and new_size. void resize(size_type n, CharT c) { - if (n <= size()) + if (n <= this->size()) this->erase(this->begin() + n, this->end()); else this->append(n - this->size(), c); @@ -963,7 +990,7 @@ class basic_string //! //! Complexity: Linear to the difference between size() and new_size. void resize(size_type n) - { resize(n, this->priv_null()); } + { resize(n, CharT(0)); } //! Effects: If n is less than or equal to capacity(), this call has no //! effect. Otherwise, it is a request for allocation of additional memory. @@ -973,8 +1000,9 @@ class basic_string //! Throws: If memory allocation allocation throws void reserve(size_type res_arg) { - if (res_arg > this->max_size()) + if (res_arg > this->max_size()){ this->throw_length_error(); + } if (this->capacity() < res_arg){ size_type n = container_detail::max_value(res_arg, this->size()) + 1; @@ -983,13 +1011,14 @@ class basic_string (allocate_new, n, new_cap, new_cap).first; size_type new_length = 0; + const pointer addr = this->priv_addr(); new_length += priv_uninitialized_copy - (this->priv_addr(), this->priv_addr() + this->priv_size(), new_start); + (addr, addr + this->priv_size(), new_start); this->priv_construct_null(new_start + new_length); this->deallocate_block(); this->is_short(false); this->priv_long_addr(new_start); - this->priv_size(new_length); + this->priv_long_size(new_length); this->priv_storage(new_cap); } } @@ -1010,8 +1039,8 @@ class basic_string //! Complexity: Linear to the number of elements in the vector. void clear() { - if (!empty()) { - Traits::assign(*this->priv_addr(), this->priv_null()); + if (!this->empty()) { + Traits::assign(*this->priv_addr(), CharT(0)); this->priv_size(0); } } @@ -1028,7 +1057,7 @@ class basic_string if(this->priv_storage() > InternalBufferChars){ //Check if we should pass from dynamically allocated buffer //to the internal storage - if(this->priv_size() < (InternalBufferChars)){ + if(this->priv_size() < InternalBufferChars){ //Dynamically allocated buffer attributes pointer long_addr = this->priv_long_addr(); size_type long_storage = this->priv_long_storage(); @@ -1085,9 +1114,10 @@ class basic_string //! Throws: std::range_error if n >= size() //! //! Complexity: Constant. - reference at(size_type n) { - if (n >= size()) - this->throw_out_of_range(); + reference at(size_type n) + { + if (n >= this->size()) + this->throw_out_of_range(); return *(this->priv_addr() + n); } @@ -1100,7 +1130,7 @@ class basic_string //! //! Complexity: Constant. const_reference at(size_type n) const { - if (n >= size()) + if (n >= this->size()) this->throw_out_of_range(); return *(this->priv_addr() + n); } @@ -1186,13 +1216,14 @@ class basic_string { const size_type old_size = this->priv_size(); if (old_size < this->capacity()){ - this->priv_construct_null(this->priv_addr() + old_size + 1); - Traits::assign(this->priv_addr()[old_size], c); + const pointer addr = this->priv_addr(); + this->priv_construct_null(addr + old_size + 1); + Traits::assign(addr[old_size], c); this->priv_size(old_size+1); } else{ //No enough memory, insert a new object at the end - this->append((size_type)1, c); + this->append(size_type(1), c); } } @@ -1266,7 +1297,8 @@ class basic_string ) { size_type cur = 0; - CharT *ptr = container_detail::to_raw_pointer(this->priv_addr()); + const pointer addr = this->priv_addr(); + CharT *ptr = container_detail::to_raw_pointer(addr); const size_type old_size = this->priv_size(); while (first != last && cur != old_size) { Traits::assign(*ptr, *first); @@ -1275,7 +1307,7 @@ class basic_string ++ptr; } if (first == last) - this->erase(this->priv_addr() + cur, this->priv_addr() + old_size); + this->erase(addr + cur, addr + old_size); else this->append(first, last); return *this; @@ -1290,9 +1322,10 @@ class basic_string //! Returns: *this basic_string& insert(size_type pos, const basic_string& s) { - if (pos > size()) + const size_type size = this->size(); + if (pos > size) this->throw_out_of_range(); - if (this->size() > this->max_size() - s.size()) + if (size > this->max_size() - s.size()) this->throw_length_error(); this->insert(this->priv_addr() + pos, s.begin(), s.end()); return *this; @@ -1308,10 +1341,12 @@ class basic_string //! Returns: *this basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n) { - if (pos1 > this->size() || pos2 > s.size()) + const size_type size = this->size(); + const size_type str_size = s.size(); + if (pos1 > size || pos2 > str_size) this->throw_out_of_range(); - size_type len = container_detail::min_value(n, s.size() - pos2); - if (this->size() > this->max_size() - len) + size_type len = container_detail::min_value(n, str_size - pos2); + if (size > this->max_size() - len) this->throw_length_error(); const CharT *beg_ptr = container_detail::to_raw_pointer(s.begin()) + pos2; const CharT *end_ptr = beg_ptr + len; @@ -1350,7 +1385,7 @@ class basic_string //! Returns: *this basic_string& insert(size_type pos, const CharT* s) { - if (pos > size()) + if (pos > this->size()) this->throw_out_of_range(); size_type len = Traits::length(s); if (this->size() > this->max_size() - len) @@ -1457,11 +1492,11 @@ class basic_string //Reuse same buffer if(enough_capacity){ - const size_type elems_after = old_size - (p - this->priv_addr()); + const size_type elems_after = old_size - (p - old_start); const size_type old_length = old_size; if (elems_after >= n) { - const pointer pointer_past_last = this->priv_addr() + old_size + 1; - priv_uninitialized_copy(this->priv_addr() + (old_size - n + 1), + const pointer pointer_past_last = old_start + old_size + 1; + priv_uninitialized_copy(old_start + (old_size - n + 1), pointer_past_last, pointer_past_last); this->priv_size(old_size+n); @@ -1474,12 +1509,13 @@ class basic_string ForwardIter mid = first; std::advance(mid, elems_after + 1); - priv_uninitialized_copy(mid, last, this->priv_addr() + old_size + 1); - this->priv_size(old_size + (n - elems_after)); + priv_uninitialized_copy(mid, last, old_start + old_size + 1); + const size_type newer_size = old_size + (n - elems_after); + this->priv_size(newer_size); priv_uninitialized_copy - (p, const_iterator(this->priv_addr() + old_length + 1), - this->priv_addr() + this->priv_size()); - this->priv_size(this->priv_size() + elems_after); + (p, const_iterator(old_start + old_length + 1), + old_start + newer_size); + this->priv_size(newer_size + elems_after); this->priv_copy(first, mid, const_cast(container_detail::to_raw_pointer(p))); } } @@ -1490,11 +1526,11 @@ class basic_string size_type new_length = 0; //This can't throw, since characters are POD new_length += priv_uninitialized_copy - (const_iterator(this->priv_addr()), p, new_start); + (const_iterator(old_start), p, new_start); new_length += priv_uninitialized_copy (first, last, new_start + new_length); new_length += priv_uninitialized_copy - (p, const_iterator(this->priv_addr() + old_size), + (p, const_iterator(old_start + old_size), new_start + new_length); this->priv_construct_null(new_start + new_length); @@ -1542,9 +1578,10 @@ class basic_string //! Returns: *this basic_string& erase(size_type pos = 0, size_type n = npos) { - if (pos > size()) + if (pos > this->size()) this->throw_out_of_range(); - erase(this->priv_addr() + pos, this->priv_addr() + pos + container_detail::min_value(n, size() - pos)); + const pointer addr = this->priv_addr(); + erase(addr + pos, addr + pos + container_detail::min_value(n, this->size() - pos)); return *this; } @@ -1597,7 +1634,7 @@ class basic_string void pop_back() { const size_type old_size = this->priv_size(); - Traits::assign(this->priv_addr()[old_size-1], this->priv_null()); + Traits::assign(this->priv_addr()[old_size-1], CharT(0)); this->priv_size(old_size-1);; } @@ -1610,13 +1647,14 @@ class basic_string //! Returns: *this basic_string& replace(size_type pos1, size_type n1, const basic_string& str) { - if (pos1 > size()) + if (pos1 > this->size()) this->throw_out_of_range(); - const size_type len = container_detail::min_value(n1, size() - pos1); + const size_type len = container_detail::min_value(n1, this->size() - pos1); if (this->size() - len >= this->max_size() - str.size()) this->throw_length_error(); - return this->replace( const_iterator(this->priv_addr() + pos1) - , const_iterator(this->priv_addr() + pos1 + len) + const pointer addr = this->priv_addr(); + return this->replace( const_iterator(addr + pos1) + , const_iterator(addr + pos1 + len) , str.begin(), str.end()); } @@ -1632,14 +1670,16 @@ class basic_string basic_string& replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2) { - if (pos1 > size() || pos2 > str.size()) + if (pos1 > this->size() || pos2 > str.size()) this->throw_out_of_range(); - const size_type len1 = container_detail::min_value(n1, size() - pos1); + const size_type len1 = container_detail::min_value(n1, this->size() - pos1); const size_type len2 = container_detail::min_value(n2, str.size() - pos2); if (this->size() - len1 >= this->max_size() - len2) this->throw_length_error(); - return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len1, - str.priv_addr() + pos2, str.priv_addr() + pos2 + len2); + const pointer addr = this->priv_addr(); + const pointer straddr = str.priv_addr(); + return this->replace(addr + pos1, addr + pos1 + len1, + straddr + pos2, straddr + pos2 + len2); } //! Requires: pos1 <= size() and s points to an array of at least n2 elements of CharT. @@ -1658,12 +1698,13 @@ class basic_string //! Returns: *this basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2) { - if (pos1 > size()) + if (pos1 > this->size()) this->throw_out_of_range(); - const size_type len = container_detail::min_value(n1, size() - pos1); + const size_type len = container_detail::min_value(n1, this->size() - pos1); if (n2 > this->max_size() || size() - len >= this->max_size() - n2) this->throw_length_error(); - return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len, s, s + n2); + const pointer addr = this->priv_addr(); + return this->replace(addr + pos1, addr + pos1 + len, s, s + n2); } //! Requires: pos1 <= size() and s points to an array of at least n2 elements of CharT. @@ -1682,13 +1723,14 @@ class basic_string //! Returns: *this basic_string& replace(size_type pos, size_type n1, const CharT* s) { - if (pos > size()) + if (pos > this->size()) this->throw_out_of_range(); - const size_type len = container_detail::min_value(n1, size() - pos); + const size_type len = container_detail::min_value(n1, this->size() - pos); const size_type n2 = Traits::length(s); - if (n2 > this->max_size() || size() - len >= this->max_size() - n2) + if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2) this->throw_length_error(); - return this->replace(this->priv_addr() + pos, this->priv_addr() + pos + len, + const pointer addr = this->priv_addr(); + return this->replace(addr + pos, addr + pos + len, s, s + Traits::length(s)); } @@ -1702,12 +1744,13 @@ class basic_string //! Returns: *this basic_string& replace(size_type pos1, size_type n1, size_type n2, CharT c) { - if (pos1 > size()) + if (pos1 > this->size()) this->throw_out_of_range(); - const size_type len = container_detail::min_value(n1, size() - pos1); - if (n2 > this->max_size() || size() - len >= this->max_size() - n2) + const size_type len = container_detail::min_value(n1, this->size() - pos1); + if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2) this->throw_length_error(); - return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len, n2, c); + const pointer addr = this->priv_addr(); + return this->replace(addr + pos1, addr + pos1 + len, n2, c); } //! Requires: [begin(),i1) and [i1,i2) are valid ranges. @@ -1829,9 +1872,9 @@ class basic_string //! Returns: rlen size_type copy(CharT* s, size_type n, size_type pos = 0) const { - if (pos > size()) + if (pos > this->size()) this->throw_out_of_range(); - const size_type len = container_detail::min_value(n, size() - pos); + const size_type len = container_detail::min_value(n, this->size() - pos); Traits::copy(s, container_detail::to_raw_pointer(this->priv_addr() + pos), len); return len; } @@ -1880,12 +1923,13 @@ class basic_string //! Returns: find(basic_string(s,n),pos). size_type find(const CharT* s, size_type pos, size_type n) const { - if (pos + n > size()) + if (pos + n > this->size()) return npos; else { - pointer finish = this->priv_addr() + this->priv_size(); + const pointer addr = this->priv_addr(); + pointer finish = addr + this->priv_size(); const const_iterator result = - std::search(container_detail::to_raw_pointer(this->priv_addr() + pos), + std::search(container_detail::to_raw_pointer(addr + pos), container_detail::to_raw_pointer(finish), s, s + n, Eq_traits()); return result != finish ? result - begin() : npos; @@ -1898,19 +1942,21 @@ class basic_string //! //! Returns: find(basic_string(s), pos). size_type find(const CharT* s, size_type pos = 0) const - { return find(s, pos, Traits::length(s)); } + { return this->find(s, pos, Traits::length(s)); } //! Throws: Nothing //! //! Returns: find(basic_string(1,c), pos). size_type find(CharT c, size_type pos = 0) const { - if (pos >= size()) + const size_type size = this->size(); + if (pos >= size) return npos; else { - pointer finish = this->priv_addr() + this->priv_size(); + const pointer addr = this->priv_addr(); + pointer finish = addr + size; const const_iterator result = - std::find_if(this->priv_addr() + pos, finish, + std::find_if(addr + pos, finish, std::bind2nd(Eq_traits(), c)); return result != finish ? result - begin() : npos; } @@ -1934,7 +1980,7 @@ class basic_string //! Returns: rfind(basic_string(s, n), pos). size_type rfind(const CharT* s, size_type pos, size_type n) const { - const size_type len = size(); + const size_type len = this->size(); if (n > len) return npos; @@ -1963,7 +2009,7 @@ class basic_string //! Returns: rfind(basic_string(1,c),pos). size_type rfind(CharT c, size_type pos = npos) const { - const size_type len = size(); + const size_type len = this->size(); if (len < 1) return npos; @@ -1993,14 +2039,15 @@ class basic_string //! Returns: find_first_of(basic_string(s, n), pos). size_type find_first_of(const CharT* s, size_type pos, size_type n) const { - if (pos >= size()) + const size_type size = this->size(); + if (pos >= size) return npos; else { - pointer finish = this->priv_addr() + this->priv_size(); - const_iterator result = std::find_first_of(this->priv_addr() + pos, finish, - s, s + n, - Eq_traits()); - return result != finish ? result - begin() : npos; + const pointer addr = this->priv_addr(); + pointer finish = addr + size; + const_iterator result = std::find_first_of + (addr + pos, finish, s, s + n, Eq_traits()); + return result != finish ? result - this->begin() : npos; } } @@ -2037,17 +2084,17 @@ class basic_string //! Returns: find_last_of(basic_string(s, n), pos). size_type find_last_of(const CharT* s, size_type pos, size_type n) const { - const size_type len = size(); + const size_type len = this->size(); if (len < 1) return npos; else { - const const_iterator last = this->priv_addr() + container_detail::min_value(len - 1, pos) + 1; + const pointer addr = this->priv_addr(); + const const_iterator last = addr + container_detail::min_value(len - 1, pos) + 1; const const_reverse_iterator rresult = std::find_first_of(const_reverse_iterator(last), rend(), - s, s + n, - Eq_traits()); - return rresult != rend() ? (rresult.base() - 1) - this->priv_addr() : npos; + s, s + n, Eq_traits()); + return rresult != rend() ? (rresult.base() - 1) - addr : npos; } } @@ -2083,13 +2130,14 @@ class basic_string //! Returns: find_first_not_of(basic_string(s, n), pos). size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const { - if (pos > size()) + if (pos > this->size()) return npos; else { - const pointer finish = this->priv_addr() + this->priv_size(); - const const_iterator result = std::find_if(this->priv_addr() + pos, finish, - Not_within_traits(s, s + n)); - return result != finish ? result - this->priv_addr() : npos; + const pointer addr = this->priv_addr(); + const pointer finish = addr + this->priv_size(); + const const_iterator result = std::find_if + (addr + pos, finish, Not_within_traits(s, s + n)); + return result != finish ? result - addr : npos; } } @@ -2106,12 +2154,13 @@ class basic_string //! Returns: find_first_not_of(basic_string(1, c), pos). size_type find_first_not_of(CharT c, size_type pos = 0) const { - if (pos > size()) + if (pos > this->size()) return npos; else { - const pointer finish = this->priv_addr() + this->priv_size(); + const pointer addr = this->priv_addr(); + const pointer finish = addr + this->priv_size(); const const_iterator result - = std::find_if(this->priv_addr() + pos, finish, + = std::find_if(addr + pos, finish, std::not1(std::bind2nd(Eq_traits(), c))); return result != finish ? result - begin() : npos; } @@ -2134,7 +2183,7 @@ class basic_string //! Returns: find_last_not_of(basic_string(s, n), pos). size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const { - const size_type len = size(); + const size_type len = this->size(); if (len < 1) return npos; @@ -2160,7 +2209,7 @@ class basic_string //! Returns: find_last_not_of(basic_string(1, c), pos). size_type find_last_not_of(CharT c, size_type pos = npos) const { - const size_type len = size(); + const size_type len = this->size(); if (len < 1) return npos; @@ -2183,10 +2232,11 @@ class basic_string //! Returns: basic_string(data()+pos,rlen). basic_string substr(size_type pos = 0, size_type n = npos) const { - if (pos > size()) + if (pos > this->size()) this->throw_out_of_range(); - return basic_string(this->priv_addr() + pos, - this->priv_addr() + pos + container_detail::min_value(n, size() - pos), this->alloc()); + const pointer addr = this->priv_addr(); + return basic_string(addr + pos, + addr + pos + container_detail::min_value(n, size() - pos), this->alloc()); } //! Effects: Determines the effective length rlen of the string to copy as @@ -2199,7 +2249,11 @@ class basic_string //! Otherwise, returns a value < 0 if size() < str.size(), a 0 value if size() == str.size(), //! and value > 0 if size() > str.size() int compare(const basic_string& str) const - { return s_compare(this->priv_addr(), this->priv_addr() + this->priv_size(), str.priv_addr(), str.priv_addr() + str.priv_size()); } + { + const pointer addr = this->priv_addr(); + const pointer str_addr = str.priv_addr(); + return s_compare(addr, addr + this->priv_size(), str_addr, str_addr + str.priv_size()); + } //! Requires: pos1 <= size() //! @@ -2211,11 +2265,13 @@ class basic_string //! Returns:basic_string(*this,pos1,n1).compare(str). int compare(size_type pos1, size_type n1, const basic_string& str) const { - if (pos1 > size()) + if (pos1 > this->size()) this->throw_out_of_range(); - return s_compare(this->priv_addr() + pos1, - this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1), - str.priv_addr(), str.priv_addr() + str.priv_size()); + const pointer addr = this->priv_addr(); + const pointer str_addr = str.priv_addr(); + return s_compare(addr + pos1, + addr + pos1 + container_detail::min_value(n1, this->size() - pos1), + str_addr, str_addr + str.priv_size()); } //! Requires: pos1 <= size() and pos2 <= str.size() @@ -2228,19 +2284,24 @@ class basic_string //! Returns: basic_string(*this, pos1, n1).compare(basic_string(str, pos2, n2)). int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2) const { - if (pos1 > size() || pos2 > str.size()) + if (pos1 > this->size() || pos2 > str.size()) this->throw_out_of_range(); - return s_compare(this->priv_addr() + pos1, - this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1), - str.priv_addr() + pos2, - str.priv_addr() + pos2 + container_detail::min_value(n2, size() - pos2)); + const pointer addr = this->priv_addr(); + const pointer str_addr = str.priv_addr(); + return s_compare(addr + pos1, + addr + pos1 + container_detail::min_value(n1, this->size() - pos1), + str_addr + pos2, + str_addr + pos2 + container_detail::min_value(n2, str.size() - pos2)); } //! Throws: Nothing //! //! Returns: compare(basic_string(s)). int compare(const CharT* s) const - { return s_compare(this->priv_addr(), this->priv_addr() + this->priv_size(), s, s + Traits::length(s)); } + { + const pointer addr = this->priv_addr(); + return s_compare(addr, addr + this->priv_size(), s, s + Traits::length(s)); + } //! Requires: pos1 > size() and s points to an array of at least n2 elements of CharT. @@ -2251,10 +2312,11 @@ class basic_string int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const { - if (pos1 > size()) + if (pos1 > this->size()) this->throw_out_of_range(); - return s_compare(this->priv_addr() + pos1, - this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1), + const pointer addr = this->priv_addr(); + return s_compare( addr + pos1, + addr + pos1 + container_detail::min_value(n1, this->size() - pos1), s, s + n2); } @@ -2322,15 +2384,12 @@ class basic_string } void priv_construct_null(pointer p) - { this->construct(p, 0); } - - static CharT priv_null() - { return (CharT) 0; } + { this->construct(p, CharT(0)); } // Helper functions used by constructors. It is a severe error for // any of them to be called anywhere except from within constructors. void priv_terminate_string() - { this->priv_construct_null(this->priv_addr() + this->priv_size()); } + { this->priv_construct_null(this->priv_end_addr()); } template inline void priv_uninitialized_fill_n(FwdIt first, Count count, const CharT val) @@ -2377,26 +2436,7 @@ class basic_string BOOST_CATCH_END return (constructed); } -/* - template - basic_string& priv_assign_dispatch(InputIter f, InputIter l, container_detail::false_) - { - size_type cur = 0; - CharT *ptr = container_detail::to_raw_pointer(this->priv_addr()); - const size_type old_size = this->priv_size(); - while (f != l && cur != old_size) { - Traits::assign(*ptr, *f); - ++f; - ++cur; - ++ptr; - } - if (f == l) - this->erase(this->priv_addr() + cur, this->priv_addr() + old_size); - else - this->append(f, l); - return *this; - } -*/ + template void priv_copy(InputIterator first, InputIterator last, OutIterator result) { diff --git a/test/check_equal_containers.hpp b/test/check_equal_containers.hpp index c094711..092846f 100644 --- a/test/check_equal_containers.hpp +++ b/test/check_equal_containers.hpp @@ -58,13 +58,8 @@ bool CheckEqualContainers(const MyBoostCont *boostcont, const MyStdCont *stdcont } std::size_t i = 0; for(; itboost != itboostend; ++itboost, ++itstd, ++i){ - if(!CheckEqual(*itstd, *itboost)) return false; -/* value_type val(*itstd); - const value_type &v = *itboost; - if(v != val) - return false;*/ } return true; }