1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2008-2009. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 /* Stable vector.
11 *
12 * Copyright 2008 Joaquin M Lopez Munoz.
13 * Distributed under the Boost Software License, Version 1.0.
14 * (See accompanying file LICENSE_1_0.txt or copy at
15 * http://www.boost.org/LICENSE_1_0.txt)
16 */
17
18 #ifndef BOOST_CONTAINER_STABLE_VECTOR_HPP
19 #define BOOST_CONTAINER_STABLE_VECTOR_HPP
20
21 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
22 # pragma once
23 #endif
24
25 #include "detail/config_begin.hpp"
26 #include INCLUDE_BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
27 #include INCLUDE_BOOST_CONTAINER_CONTAINER_FWD_HPP
28 #include <boost/mpl/bool.hpp>
29 #include <boost/mpl/not.hpp>
30 #include <boost/noncopyable.hpp>
31 #include <boost/type_traits/is_integral.hpp>
32 #include INCLUDE_BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
33 #include INCLUDE_BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
34 #include INCLUDE_BOOST_CONTAINER_DETAIL_UTILITIES_HPP
35 #include INCLUDE_BOOST_CONTAINER_DETAIL_ITERATORS_HPP
36 #include INCLUDE_BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
37 #include <boost/pointer_to_other.hpp>
38 #include <boost/get_pointer.hpp>
39
40 #include <algorithm>
41 #include <stdexcept>
42 #include <memory>
43
44 ///@cond
45
46 #define STABLE_VECTOR_USE_CONTAINERS_VECTOR
47
48 #if defined (STABLE_VECTOR_USE_CONTAINERS_VECTOR)
49 #include INCLUDE_BOOST_CONTAINER_VECTOR_HPP
50 #else
51 #include <vector>
52 #endif //STABLE_VECTOR_USE_CONTAINERS_VECTOR
53
54 //#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
55
56 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
57 #include <boost/assert.hpp>
58 #endif
59
60 ///@endcond
61
62 namespace boost {
63 namespace container {
64
65 ///@cond
66
67 namespace stable_vector_detail{
68
69 template<class SmartPtr>
70 struct smart_ptr_type
71 {
72 typedef typename SmartPtr::value_type value_type;
73 typedef value_type *pointer;
getboost::container::stable_vector_detail::smart_ptr_type74 static pointer get (const SmartPtr &smartptr)
75 { return smartptr.get();}
76 };
77
78 template<class T>
79 struct smart_ptr_type<T*>
80 {
81 typedef T value_type;
82 typedef value_type *pointer;
getboost::container::stable_vector_detail::smart_ptr_type83 static pointer get (pointer ptr)
84 { return ptr;}
85 };
86
87 template<class Ptr>
get_pointer(const Ptr & ptr)88 inline typename smart_ptr_type<Ptr>::pointer get_pointer(const Ptr &ptr)
89 { return smart_ptr_type<Ptr>::get(ptr); }
90
91 template <class C>
92 class clear_on_destroy
93 {
94 public:
clear_on_destroy(C & c)95 clear_on_destroy(C &c)
96 : c_(c), do_clear_(true)
97 {}
98
release()99 void release()
100 { do_clear_ = false; }
101
~clear_on_destroy()102 ~clear_on_destroy()
103 {
104 if(do_clear_){
105 c_.clear();
106 c_.clear_pool();
107 }
108 }
109
110 private:
111 clear_on_destroy(const clear_on_destroy &);
112 clear_on_destroy &operator=(const clear_on_destroy &);
113 C &c_;
114 bool do_clear_;
115 };
116
117 template<class VoidPtr>
118 struct node_type_base
119 {/*
120 node_type_base(VoidPtr p)
121 : up(p)
122 {}*/
node_type_baseboost::container::stable_vector_detail::node_type_base123 node_type_base()
124 {}
set_pointerboost::container::stable_vector_detail::node_type_base125 void set_pointer(VoidPtr p)
126 { up = p; }
127
128 VoidPtr up;
129 };
130
131 template<typename VoidPointer, typename T>
132 struct node_type
133 : public node_type_base<VoidPointer>
134 {
135 #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
136
node_typeboost::container::stable_vector_detail::node_type137 node_type()
138 : value()
139 {}
140
141 template<class ...Args>
node_typeboost::container::stable_vector_detail::node_type142 node_type(Args &&...args)
143 : value(BOOST_CONTAINER_MOVE_NAMESPACE::forward<Args>(args)...)
144 {}
145
146 #else //BOOST_CONTAINERS_PERFECT_FORWARDING
147
148 node_type()
149 : value()
150 {}
151
152 #define BOOST_PP_LOCAL_MACRO(n) \
153 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
154 node_type(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
155 : value(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \
156 {} \
157 //!
158 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
159 #include BOOST_PP_LOCAL_ITERATE()
160
161 #endif//BOOST_CONTAINERS_PERFECT_FORWARDING
162
set_pointerboost::container::stable_vector_detail::node_type163 void set_pointer(VoidPointer p)
164 { node_type_base<VoidPointer>::set_pointer(p); }
165
166 T value;
167 };
168
169 template<typename T, typename Reference, typename Pointer>
170 class iterator
171 : public std::iterator< std::random_access_iterator_tag
172 , typename std::iterator_traits<Pointer>::value_type
173 , typename std::iterator_traits<Pointer>::difference_type
174 , Pointer
175 , Reference>
176 {
177
178 typedef typename boost::pointer_to_other
179 <Pointer, void>::type void_ptr;
180 typedef node_type<void_ptr, T> node_type_t;
181 typedef typename boost::pointer_to_other
182 <void_ptr, node_type_t>::type node_type_ptr_t;
183 typedef typename boost::pointer_to_other
184 <void_ptr, void_ptr>::type void_ptr_ptr;
185
186 friend class iterator<T, const T, typename boost::pointer_to_other<Pointer, T>::type>;
187
188 public:
189 typedef std::random_access_iterator_tag iterator_category;
190 typedef T value_type;
191 typedef typename std::iterator_traits
192 <Pointer>::difference_type difference_type;
193 typedef Pointer pointer;
194 typedef Reference reference;
195
iterator()196 iterator()
197 {}
198
iterator(node_type_ptr_t pn)199 explicit iterator(node_type_ptr_t pn)
200 : pn(pn)
201 {}
202
iterator(const iterator<T,T &,typename boost::pointer_to_other<Pointer,T>::type> & x)203 iterator(const iterator<T, T&, typename boost::pointer_to_other<Pointer, T>::type >& x)
204 : pn(x.pn)
205 {}
206
207 private:
node_ptr_cast(void_ptr p)208 static node_type_ptr_t node_ptr_cast(void_ptr p)
209 {
210 using boost::get_pointer;
211 return node_type_ptr_t(static_cast<node_type_t*>(stable_vector_detail::get_pointer(p)));
212 }
213
void_ptr_ptr_cast(void_ptr p)214 static void_ptr_ptr void_ptr_ptr_cast(void_ptr p)
215 {
216 using boost::get_pointer;
217 return void_ptr_ptr(static_cast<void_ptr*>(stable_vector_detail::get_pointer(p)));
218 }
219
dereference() const220 reference dereference() const
221 { return pn->value; }
equal(const iterator & x) const222 bool equal(const iterator& x) const
223 { return pn==x.pn; }
increment()224 void increment()
225 { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+1)); }
decrement()226 void decrement()
227 { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)-1)); }
advance(std::ptrdiff_t n)228 void advance(std::ptrdiff_t n)
229 { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+n)); }
distance_to(const iterator & x) const230 std::ptrdiff_t distance_to(const iterator& x)const
231 { return void_ptr_ptr_cast(x.pn->up) - void_ptr_ptr_cast(pn->up); }
232
233 public:
234 //Pointer like operators
operator *() const235 reference operator*() const { return this->dereference(); }
operator ->() const236 pointer operator->() const { return pointer(&this->dereference()); }
237
238 //Increment / Decrement
operator ++()239 iterator& operator++()
240 { this->increment(); return *this; }
241
operator ++(int)242 iterator operator++(int)
243 { iterator tmp(*this); ++*this; return iterator(tmp); }
244
operator --()245 iterator& operator--()
246 { this->decrement(); return *this; }
247
operator --(int)248 iterator operator--(int)
249 { iterator tmp(*this); --*this; return iterator(tmp); }
250
operator [](difference_type off) const251 reference operator[](difference_type off) const
252 {
253 iterator tmp(*this);
254 tmp += off;
255 return *tmp;
256 }
257
operator +=(difference_type off)258 iterator& operator+=(difference_type off)
259 {
260 pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+off));
261 return *this;
262 }
263
operator +(difference_type off) const264 iterator operator+(difference_type off) const
265 {
266 iterator tmp(*this);
267 tmp += off;
268 return tmp;
269 }
270
operator +(difference_type off,const iterator & right)271 friend iterator operator+(difference_type off, const iterator& right)
272 {
273 iterator tmp(right);
274 tmp += off;
275 return tmp;
276 }
277
operator -=(difference_type off)278 iterator& operator-=(difference_type off)
279 { *this += -off; return *this; }
280
operator -(difference_type off) const281 iterator operator-(difference_type off) const
282 {
283 iterator tmp(*this);
284 tmp -= off;
285 return tmp;
286 }
287
operator -(const iterator & right) const288 difference_type operator-(const iterator& right) const
289 {
290 void_ptr_ptr p1 = void_ptr_ptr_cast(this->pn->up);
291 void_ptr_ptr p2 = void_ptr_ptr_cast(right.pn->up);
292 return p1 - p2;
293 }
294
295 //Comparison operators
operator ==(const iterator & r) const296 bool operator== (const iterator& r) const
297 { return pn == r.pn; }
298
operator !=(const iterator & r) const299 bool operator!= (const iterator& r) const
300 { return pn != r.pn; }
301
operator <(const iterator & r) const302 bool operator< (const iterator& r) const
303 { return void_ptr_ptr_cast(pn->up) < void_ptr_ptr_cast(r.pn->up); }
304
operator <=(const iterator & r) const305 bool operator<= (const iterator& r) const
306 { return void_ptr_ptr_cast(pn->up) <= void_ptr_ptr_cast(r.pn->up); }
307
operator >(const iterator & r) const308 bool operator> (const iterator& r) const
309 { return void_ptr_ptr_cast(pn->up) > void_ptr_ptr_cast(r.pn->up); }
310
operator >=(const iterator & r) const311 bool operator>= (const iterator& r) const
312 { return void_ptr_ptr_cast(pn->up) >= void_ptr_ptr_cast(r.pn->up); }
313
314 node_type_ptr_t pn;
315 };
316
317 template<class Allocator, unsigned int Version>
318 struct select_multiallocation_chain
319 {
320 typedef typename Allocator::multiallocation_chain type;
321 };
322
323 template<class Allocator>
324 struct select_multiallocation_chain<Allocator, 1>
325 {
326 typedef typename Allocator::template
327 rebind<void>::other::pointer void_ptr;
328 typedef containers_detail::basic_multiallocation_chain
329 <void_ptr> multialloc_cached_counted;
330 typedef boost::container::containers_detail::transform_multiallocation_chain
331 <multialloc_cached_counted, typename Allocator::value_type> type;
332 };
333
334 } //namespace stable_vector_detail
335
336 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
337
338 #define STABLE_VECTOR_CHECK_INVARIANT \
339 invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \
340 BOOST_JOIN(check_invariant_,__LINE__).touch();
341 #else
342
343 #define STABLE_VECTOR_CHECK_INVARIANT
344
345 #endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
346
347 /// @endcond
348
349 //!Help taken from (<a href="http://bannalia.blogspot.com/2008/09/introducing-stablevector.html" > Introducing stable_vector</a>)
350 //!
351 //!We present stable_vector, a fully STL-compliant stable container that provides
352 //!most of the features of std::vector except element contiguity.
353 //!
354 //!General properties: stable_vector satisfies all the requirements of a container,
355 //!a reversible container and a sequence and provides all the optional operations
356 //!present in std::vector. Like std::vector, iterators are random access.
357 //!stable_vector does not provide element contiguity; in exchange for this absence,
358 //!the container is stable, i.e. references and iterators to an element of a stable_vector
359 //!remain valid as long as the element is not erased, and an iterator that has been
360 //!assigned the return value of end() always remain valid until the destruction of
361 //!the associated stable_vector.
362 //!
363 //!Operation complexity: The big-O complexities of stable_vector operations match
364 //!exactly those of std::vector. In general, insertion/deletion is constant time at
365 //!the end of the sequence and linear elsewhere. Unlike std::vector, stable_vector
366 //!does not internally perform any value_type destruction, copy or assignment
367 //!operations other than those exactly corresponding to the insertion of new
368 //!elements or deletion of stored elements, which can sometimes compensate in terms
369 //!of performance for the extra burden of doing more pointer manipulation and an
370 //!additional allocation per element.
371 //!
372 //!Exception safety: As stable_vector does not internally copy elements around, some
373 //!operations provide stronger exception safety guarantees than in std::vector:
374 template<typename T, typename Allocator>
375 class stable_vector
376 {
377 ///@cond
378 typedef typename containers_detail::
379 move_const_ref_type<T>::type insert_const_ref_type;
380 typedef typename Allocator::template
381 rebind<void>::other::pointer void_ptr;
382 typedef typename Allocator::template
383 rebind<void_ptr>::other::pointer void_ptr_ptr;
384 typedef stable_vector_detail::node_type
385 <void_ptr, T> node_type_t;
386 typedef typename Allocator::template
387 rebind<node_type_t>::other::pointer node_type_ptr_t;
388 typedef stable_vector_detail::node_type_base
389 <void_ptr> node_type_base_t;
390 typedef typename Allocator::template
391 rebind<node_type_base_t>::other::pointer node_type_base_ptr_t;
392 typedef
393 #if defined (STABLE_VECTOR_USE_CONTAINERS_VECTOR)
394 ::boost::container::
395 #else
396 ::std::
397 #endif //STABLE_VECTOR_USE_CONTAINERS_VECTOR
398 vector<void_ptr,
399 typename Allocator::
400 template rebind<void_ptr>::other
401 > impl_type;
402 typedef typename impl_type::iterator impl_iterator;
403 typedef typename impl_type::const_iterator const_impl_iterator;
404
405 typedef ::boost::container::containers_detail::
406 integral_constant<unsigned, 1> allocator_v1;
407 typedef ::boost::container::containers_detail::
408 integral_constant<unsigned, 2> allocator_v2;
409 typedef ::boost::container::containers_detail::integral_constant
410 <unsigned, boost::container::containers_detail::
411 version<Allocator>::value> alloc_version;
412 typedef typename Allocator::
413 template rebind<node_type_t>::other node_allocator_type;
414
allocate_one()415 node_type_ptr_t allocate_one()
416 { return this->allocate_one(alloc_version()); }
417
allocate_one(allocator_v1)418 node_type_ptr_t allocate_one(allocator_v1)
419 { return get_al().allocate(1); }
420
allocate_one(allocator_v2)421 node_type_ptr_t allocate_one(allocator_v2)
422 { return get_al().allocate_one(); }
423
deallocate_one(node_type_ptr_t p)424 void deallocate_one(node_type_ptr_t p)
425 { return this->deallocate_one(p, alloc_version()); }
426
deallocate_one(node_type_ptr_t p,allocator_v1)427 void deallocate_one(node_type_ptr_t p, allocator_v1)
428 { get_al().deallocate(p, 1); }
429
deallocate_one(node_type_ptr_t p,allocator_v2)430 void deallocate_one(node_type_ptr_t p, allocator_v2)
431 { get_al().deallocate_one(p); }
432
433 friend class stable_vector_detail::clear_on_destroy<stable_vector>;
434 ///@endcond
435 public:
436
437
438 // types:
439
440 typedef typename Allocator::reference reference;
441 typedef typename Allocator::const_reference const_reference;
442 typedef typename Allocator::pointer pointer;
443 typedef typename Allocator::const_pointer const_pointer;
444 typedef stable_vector_detail::iterator
445 <T,T&, pointer> iterator;
446 typedef stable_vector_detail::iterator
447 <T,const T&, const_pointer> const_iterator;
448 typedef typename impl_type::size_type size_type;
449 typedef typename iterator::difference_type difference_type;
450 typedef T value_type;
451 typedef Allocator allocator_type;
452 typedef std::reverse_iterator<iterator> reverse_iterator;
453 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
454
455 ///@cond
456 private:
457 BOOST_MOVE_MACRO_COPYABLE_AND_MOVABLE(stable_vector)
458 static const size_type ExtraPointers = 3;
459 typedef typename stable_vector_detail::
460 select_multiallocation_chain
461 < node_allocator_type
462 , alloc_version::value
463 >::type multiallocation_chain;
464 ///@endcond
465 public:
466
467 // construct/copy/destroy:
stable_vector(const Allocator & al=Allocator ())468 explicit stable_vector(const Allocator& al=Allocator())
469 : internal_data(al),impl(al)
470 {
471 STABLE_VECTOR_CHECK_INVARIANT;
472 }
473
stable_vector(size_type n)474 explicit stable_vector(size_type n)
475 : internal_data(Allocator()),impl(Allocator())
476 {
477 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
478 this->resize(n);
479 STABLE_VECTOR_CHECK_INVARIANT;
480 cod.release();
481 }
482
stable_vector(size_type n,const T & t,const Allocator & al=Allocator ())483 stable_vector(size_type n, const T& t, const Allocator& al=Allocator())
484 : internal_data(al),impl(al)
485 {
486 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
487 this->insert(this->cbegin(), n, t);
488 STABLE_VECTOR_CHECK_INVARIANT;
489 cod.release();
490 }
491
492 template <class InputIterator>
stable_vector(InputIterator first,InputIterator last,const Allocator & al=Allocator ())493 stable_vector(InputIterator first,InputIterator last,const Allocator& al=Allocator())
494 : internal_data(al),impl(al)
495 {
496 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
497 this->insert(this->cbegin(), first, last);
498 STABLE_VECTOR_CHECK_INVARIANT;
499 cod.release();
500 }
501
stable_vector(const stable_vector & x)502 stable_vector(const stable_vector& x)
503 : internal_data(x.get_al()),impl(x.get_al())
504 {
505 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
506 this->insert(this->cbegin(), x.begin(), x.end());
507 STABLE_VECTOR_CHECK_INVARIANT;
508 cod.release();
509 }
510
stable_vector(BOOST_MOVE_MACRO_RV_REF (stable_vector)x)511 stable_vector(BOOST_MOVE_MACRO_RV_REF(stable_vector) x)
512 : internal_data(x.get_al()),impl(x.get_al())
513 { this->swap(x); }
514
~stable_vector()515 ~stable_vector()
516 {
517 this->clear();
518 clear_pool();
519 }
520
operator =(BOOST_MOVE_MACRO_COPY_ASSIGN_REF (stable_vector)x)521 stable_vector& operator=(BOOST_MOVE_MACRO_COPY_ASSIGN_REF(stable_vector) x)
522 {
523 STABLE_VECTOR_CHECK_INVARIANT;
524 if (this != &x) {
525 this->assign(x.begin(), x.end());
526 }
527 return *this;
528 }
529
operator =(BOOST_MOVE_MACRO_RV_REF (stable_vector)x)530 stable_vector& operator=(BOOST_MOVE_MACRO_RV_REF(stable_vector) x)
531 {
532 if (&x != this){
533 this->swap(x);
534 x.clear();
535 }
536 return *this;
537 }
538
539 template<typename InputIterator>
assign(InputIterator first,InputIterator last)540 void assign(InputIterator first,InputIterator last)
541 {
542 assign_dispatch(first, last, boost::is_integral<InputIterator>());
543 }
544
assign(size_type n,const T & t)545 void assign(size_type n,const T& t)
546 {
547 typedef constant_iterator<value_type, difference_type> cvalue_iterator;
548 return assign_dispatch(cvalue_iterator(t, n), cvalue_iterator(), boost::mpl::false_());
549 }
550
get_allocator() const551 allocator_type get_allocator()const {return get_al();}
552
553 // iterators:
554
begin()555 iterator begin()
556 { return (impl.empty()) ? end(): iterator(node_ptr_cast(impl.front())) ; }
557
begin() const558 const_iterator begin()const
559 { return (impl.empty()) ? cend() : const_iterator(node_ptr_cast(impl.front())) ; }
560
end()561 iterator end() {return iterator(get_end_node());}
end() const562 const_iterator end()const {return const_iterator(get_end_node());}
563
rbegin()564 reverse_iterator rbegin() {return reverse_iterator(this->end());}
rbegin() const565 const_reverse_iterator rbegin()const {return const_reverse_iterator(this->end());}
rend()566 reverse_iterator rend() {return reverse_iterator(this->begin());}
rend() const567 const_reverse_iterator rend()const {return const_reverse_iterator(this->begin());}
568
cbegin() const569 const_iterator cbegin()const {return this->begin();}
cend() const570 const_iterator cend()const {return this->end();}
crbegin() const571 const_reverse_iterator crbegin()const{return this->rbegin();}
crend() const572 const_reverse_iterator crend()const {return this->rend();}
573
574 // capacity:
size() const575 size_type size() const
576 { return impl.empty() ? 0 : (impl.size() - ExtraPointers); }
577
max_size() const578 size_type max_size() const
579 { return impl.max_size() - ExtraPointers; }
580
capacity() const581 size_type capacity() const
582 {
583 if(!impl.capacity()){
584 return 0;
585 }
586 else{
587 const size_type num_nodes = this->impl.size() + this->internal_data.pool_size;
588 const size_type num_buck = this->impl.capacity();
589 return (num_nodes < num_buck) ? num_nodes : num_buck;
590 }
591 }
592
empty() const593 bool empty() const
594 { return impl.empty() || impl.size() == ExtraPointers; }
595
resize(size_type n,const T & t)596 void resize(size_type n, const T& t)
597 {
598 STABLE_VECTOR_CHECK_INVARIANT;
599 if(n > size())
600 this->insert(this->cend(), n - this->size(), t);
601 else if(n < this->size())
602 this->erase(this->cbegin() + n, this->cend());
603 }
604
resize(size_type n)605 void resize(size_type n)
606 {
607 typedef default_construct_iterator<value_type, difference_type> default_iterator;
608 STABLE_VECTOR_CHECK_INVARIANT;
609 if(n > size())
610 this->insert(this->cend(), default_iterator(n - this->size()), default_iterator());
611 else if(n < this->size())
612 this->erase(this->cbegin() + n, this->cend());
613 }
614
reserve(size_type n)615 void reserve(size_type n)
616 {
617 STABLE_VECTOR_CHECK_INVARIANT;
618 if(n > this->max_size())
619 throw std::bad_alloc();
620
621 size_type size = this->size();
622 size_type old_capacity = this->capacity();
623 if(n > old_capacity){
624 this->initialize_end_node(n);
625 const void * old_ptr = &impl[0];
626 impl.reserve(n + ExtraPointers);
627 bool realloced = &impl[0] != old_ptr;
628 //Fix the pointers for the newly allocated buffer
629 if(realloced){
630 this->align_nodes(impl.begin(), impl.begin()+size+1);
631 }
632 //Now fill pool if data is not enough
633 if((n - size) > this->internal_data.pool_size){
634 this->add_to_pool((n - size) - this->internal_data.pool_size);
635 }
636 }
637 }
638
639 // element access:
640
operator [](size_type n)641 reference operator[](size_type n){return value(impl[n]);}
operator [](size_type n) const642 const_reference operator[](size_type n)const{return value(impl[n]);}
643
at(size_type n) const644 const_reference at(size_type n)const
645 {
646 if(n>=size())
647 throw std::out_of_range("invalid subscript at stable_vector::at");
648 return operator[](n);
649 }
650
at(size_type n)651 reference at(size_type n)
652 {
653 if(n>=size())
654 throw std::out_of_range("invalid subscript at stable_vector::at");
655 return operator[](n);
656 }
657
front()658 reference front()
659 { return value(impl.front()); }
660
front() const661 const_reference front()const
662 { return value(impl.front()); }
663
back()664 reference back()
665 { return value(*(&impl.back() - ExtraPointers)); }
666
back() const667 const_reference back()const
668 { return value(*(&impl.back() - ExtraPointers)); }
669
670 // modifiers:
671
push_back(insert_const_ref_type x)672 void push_back(insert_const_ref_type x)
673 { return priv_push_back(x); }
674
675 #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
push_back(T & x)676 void push_back(T &x) { push_back(const_cast<const T &>(x)); }
677
678 template<class U>
push_back(const U & u,typename containers_detail::enable_if_c<containers_detail::is_same<T,U>::value &&!::BOOST_CONTAINER_MOVE_NAMESPACE::is_movable<U>::value>::type * =0)679 void push_back(const U &u, typename containers_detail::enable_if_c<containers_detail::is_same<T, U>::value && !::BOOST_CONTAINER_MOVE_NAMESPACE::is_movable<U>::value >::type* =0)
680 { return priv_push_back(u); }
681 #endif
682
push_back(BOOST_MOVE_MACRO_RV_REF (T)t)683 void push_back(BOOST_MOVE_MACRO_RV_REF(T) t)
684 { this->insert(end(), BOOST_CONTAINER_MOVE_NAMESPACE::move(t)); }
685
pop_back()686 void pop_back()
687 { this->erase(this->end()-1); }
688
insert(const_iterator position,insert_const_ref_type x)689 iterator insert(const_iterator position, insert_const_ref_type x)
690 { return this->priv_insert(position, x); }
691
692 #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
insert(const_iterator position,T & x)693 iterator insert(const_iterator position, T &x) { return this->insert(position, const_cast<const T &>(x)); }
694
695 template<class U>
insert(const_iterator position,const U & u,typename containers_detail::enable_if_c<containers_detail::is_same<T,U>::value &&!::BOOST_CONTAINER_MOVE_NAMESPACE::is_movable<U>::value>::type * =0)696 iterator insert(const_iterator position, const U &u, typename containers_detail::enable_if_c<containers_detail::is_same<T, U>::value && !::BOOST_CONTAINER_MOVE_NAMESPACE::is_movable<U>::value >::type* =0)
697 { return this->priv_insert(position, u); }
698 #endif
699
insert(const_iterator position,BOOST_MOVE_MACRO_RV_REF (T)x)700 iterator insert(const_iterator position, BOOST_MOVE_MACRO_RV_REF(T) x)
701 {
702 typedef repeat_iterator<T, difference_type> repeat_it;
703 typedef BOOST_CONTAINER_MOVE_NAMESPACE::move_iterator<repeat_it> repeat_move_it;
704 //Just call more general insert(pos, size, value) and return iterator
705 size_type pos_n = position - cbegin();
706 this->insert(position
707 ,repeat_move_it(repeat_it(x, 1))
708 ,repeat_move_it(repeat_it()));
709 return iterator(this->begin() + pos_n);
710 }
711
insert(const_iterator position,size_type n,const T & t)712 void insert(const_iterator position, size_type n, const T& t)
713 {
714 STABLE_VECTOR_CHECK_INVARIANT;
715 this->insert_not_iter(position, n, t);
716 }
717
718 template <class InputIterator>
insert(const_iterator position,InputIterator first,InputIterator last)719 void insert(const_iterator position,InputIterator first, InputIterator last)
720 {
721 STABLE_VECTOR_CHECK_INVARIANT;
722 this->insert_iter(position,first,last,
723 boost::mpl::not_<boost::is_integral<InputIterator> >());
724 }
725
726 #if defined(BOOST_CONTAINERS_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
727
728 //! <b>Effects</b>: Inserts an object of type T constructed with
729 //! std::forward<Args>(args)... in the end of the vector.
730 //!
731 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
732 //!
733 //! <b>Complexity</b>: Amortized constant time.
734 template<class ...Args>
emplace_back(Args &&...args)735 void emplace_back(Args &&...args)
736 {
737 typedef emplace_functor<node_type_t, Args...> EmplaceFunctor;
738 typedef emplace_iterator<node_type_t, EmplaceFunctor> EmplaceIterator;
739 EmplaceFunctor &&ef = EmplaceFunctor(BOOST_CONTAINER_MOVE_NAMESPACE::forward<Args>(args)...);
740 this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
741 }
742
743 //! <b>Requires</b>: position must be a valid iterator of *this.
744 //!
745 //! <b>Effects</b>: Inserts an object of type T constructed with
746 //! std::forward<Args>(args)... before position
747 //!
748 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
749 //!
750 //! <b>Complexity</b>: If position is end(), amortized constant time
751 //! Linear time otherwise.
752 template<class ...Args>
emplace(const_iterator position,Args &&...args)753 iterator emplace(const_iterator position, Args && ...args)
754 {
755 //Just call more general insert(pos, size, value) and return iterator
756 size_type pos_n = position - cbegin();
757 typedef emplace_functor<node_type_t, Args...> EmplaceFunctor;
758 typedef emplace_iterator<node_type_t, EmplaceFunctor> EmplaceIterator;
759 EmplaceFunctor &&ef = EmplaceFunctor(BOOST_CONTAINER_MOVE_NAMESPACE::forward<Args>(args)...);
760 this->insert(position, EmplaceIterator(ef), EmplaceIterator());
761 return iterator(this->begin() + pos_n);
762 }
763
764 #else
765
emplace_back()766 void emplace_back()
767 {
768 typedef emplace_functor<node_type_t> EmplaceFunctor;
769 typedef emplace_iterator<node_type_t, EmplaceFunctor> EmplaceIterator;
770 EmplaceFunctor ef;
771 this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
772 }
773
emplace(const_iterator position)774 iterator emplace(const_iterator position)
775 {
776 typedef emplace_functor<node_type_t> EmplaceFunctor;
777 typedef emplace_iterator<node_type_t, EmplaceFunctor> EmplaceIterator;
778 EmplaceFunctor ef;
779 size_type pos_n = position - this->cbegin();
780 this->insert(position, EmplaceIterator(ef), EmplaceIterator());
781 return iterator(this->begin() + pos_n);
782 }
783
784 #define BOOST_PP_LOCAL_MACRO(n) \
785 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
786 void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
787 { \
788 typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
789 <node_type_t, BOOST_PP_ENUM_PARAMS(n, P)> EmplaceFunctor; \
790 typedef emplace_iterator<node_type_t, EmplaceFunctor> EmplaceIterator; \
791 EmplaceFunctor ef(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
792 this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator()); \
793 } \
794 \
795 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
796 iterator emplace(const_iterator pos, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
797 { \
798 typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
799 <node_type_t, BOOST_PP_ENUM_PARAMS(n, P)> EmplaceFunctor; \
800 typedef emplace_iterator<node_type_t, EmplaceFunctor> EmplaceIterator; \
801 EmplaceFunctor ef(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
802 size_type pos_n = pos - this->cbegin(); \
803 this->insert(pos, EmplaceIterator(ef), EmplaceIterator()); \
804 return iterator(this->begin() + pos_n); \
805 } \
806 //!
807 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
808 #include BOOST_PP_LOCAL_ITERATE()
809
810 #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
811
erase(const_iterator position)812 iterator erase(const_iterator position)
813 {
814 STABLE_VECTOR_CHECK_INVARIANT;
815 difference_type d=position-this->cbegin();
816 impl_iterator it=impl.begin()+d;
817 this->delete_node(*it);
818 impl.erase(it);
819 this->align_nodes(impl.begin()+d,get_last_align());
820 return this->begin()+d;
821 }
822
erase(const_iterator first,const_iterator last)823 iterator erase(const_iterator first, const_iterator last)
824 { return priv_erase(first, last, alloc_version()); }
825
swap(stable_vector & x)826 void swap(stable_vector & x)
827 {
828 STABLE_VECTOR_CHECK_INVARIANT;
829 this->swap_impl(*this,x);
830 }
831
clear()832 void clear()
833 { this->erase(this->cbegin(),this->cend()); }
834
835 /// @cond
836 private:
837
priv_insert(const_iterator position,const value_type & t)838 iterator priv_insert(const_iterator position, const value_type &t)
839 {
840 typedef constant_iterator<value_type, difference_type> cvalue_iterator;
841 return this->insert_iter(position, cvalue_iterator(t, 1), cvalue_iterator(), std::forward_iterator_tag());
842 }
843
priv_push_back(const value_type & t)844 void priv_push_back(const value_type &t)
845 { this->insert(end(), t); }
846
clear_pool(allocator_v1)847 void clear_pool(allocator_v1)
848 {
849 if(!impl.empty() && impl.back()){
850 void_ptr &p1 = *(impl.end()-2);
851 void_ptr &p2 = impl.back();
852
853 multiallocation_chain holder;
854 holder.incorporate_after(holder.before_begin(), p1, p2, this->internal_data.pool_size);
855 while(!holder.empty()){
856 node_type_ptr_t n = holder.front();
857 holder.pop_front();
858 this->deallocate_one(n);
859 }
860 p1 = p2 = 0;
861 this->internal_data.pool_size = 0;
862 }
863 }
864
clear_pool(allocator_v2)865 void clear_pool(allocator_v2)
866 {
867
868 if(!impl.empty() && impl.back()){
869 void_ptr &p1 = *(impl.end()-2);
870 void_ptr &p2 = impl.back();
871 multiallocation_chain holder;
872 holder.incorporate_after(holder.before_begin(), p1, p2, internal_data.pool_size);
873 get_al().deallocate_individual(BOOST_CONTAINER_MOVE_NAMESPACE::move(holder));
874 p1 = p2 = 0;
875 this->internal_data.pool_size = 0;
876 }
877 }
878
clear_pool()879 void clear_pool()
880 {
881 this->clear_pool(alloc_version());
882 }
883
add_to_pool(size_type n)884 void add_to_pool(size_type n)
885 {
886 this->add_to_pool(n, alloc_version());
887 }
888
add_to_pool(size_type n,allocator_v1)889 void add_to_pool(size_type n, allocator_v1)
890 {
891 size_type remaining = n;
892 while(remaining--){
893 this->put_in_pool(this->allocate_one());
894 }
895 }
896
add_to_pool(size_type n,allocator_v2)897 void add_to_pool(size_type n, allocator_v2)
898 {
899 void_ptr &p1 = *(impl.end()-2);
900 void_ptr &p2 = impl.back();
901 multiallocation_chain holder;
902 holder.incorporate_after(holder.before_begin(), p1, p2, internal_data.pool_size);
903 BOOST_STATIC_ASSERT((::BOOST_CONTAINER_MOVE_NAMESPACE::is_movable<multiallocation_chain>::value == true));
904 multiallocation_chain m (get_al().allocate_individual(n));
905 holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
906 this->internal_data.pool_size += n;
907 std::pair<void_ptr, void_ptr> data(holder.extract_data());
908 p1 = data.first;
909 p2 = data.second;
910 }
911
put_in_pool(node_type_ptr_t p)912 void put_in_pool(node_type_ptr_t p)
913 {
914 void_ptr &p1 = *(impl.end()-2);
915 void_ptr &p2 = impl.back();
916 multiallocation_chain holder;
917 holder.incorporate_after(holder.before_begin(), p1, p2, internal_data.pool_size);
918 holder.push_front(p);
919 ++this->internal_data.pool_size;
920 std::pair<void_ptr, void_ptr> ret(holder.extract_data());
921 p1 = ret.first;
922 p2 = ret.second;
923 }
924
get_from_pool()925 node_type_ptr_t get_from_pool()
926 {
927 if(!impl.back()){
928 return node_type_ptr_t(0);
929 }
930 else{
931 void_ptr &p1 = *(impl.end()-2);
932 void_ptr &p2 = impl.back();
933 multiallocation_chain holder;
934 holder.incorporate_after(holder.before_begin(), p1, p2, internal_data.pool_size);
935 node_type_ptr_t ret = holder.front();
936 holder.pop_front();
937 --this->internal_data.pool_size;
938 if(!internal_data.pool_size){
939 p1 = p2 = 0;
940 }
941 else{
942 std::pair<void_ptr, void_ptr> data(holder.extract_data());
943 p1 = data.first;
944 p2 = data.second;
945 }
946 return ret;
947 }
948 }
949
insert_iter_prolog(size_type n,difference_type d)950 void insert_iter_prolog(size_type n, difference_type d)
951 {
952 initialize_end_node(n);
953 const void* old_ptr = &impl[0];
954 //size_type old_capacity = capacity();
955 //size_type old_size = size();
956 impl.insert(impl.begin()+d, n, 0);
957 bool realloced = &impl[0] != old_ptr;
958 //Fix the pointers for the newly allocated buffer
959 if(realloced){
960 align_nodes(impl.begin(), impl.begin()+d);
961 }
962 }
963
964 template<typename InputIterator>
assign_dispatch(InputIterator first,InputIterator last,boost::mpl::false_)965 void assign_dispatch(InputIterator first, InputIterator last, boost::mpl::false_)
966 {
967 STABLE_VECTOR_CHECK_INVARIANT;
968 iterator first1 = this->begin();
969 iterator last1 = this->end();
970 for ( ; first1 != last1 && first != last; ++first1, ++first)
971 *first1 = *first;
972 if (first == last){
973 this->erase(first1, last1);
974 }
975 else{
976 this->insert(last1, first, last);
977 }
978 }
979
980 template<typename Integer>
assign_dispatch(Integer n,Integer t,boost::mpl::true_)981 void assign_dispatch(Integer n, Integer t, boost::mpl::true_)
982 {
983 typedef constant_iterator<value_type, difference_type> cvalue_iterator;
984 this->assign_dispatch(cvalue_iterator(t, n), cvalue_iterator(), boost::mpl::false_());
985 }
986
priv_erase(const_iterator first,const_iterator last,allocator_v1)987 iterator priv_erase(const_iterator first, const_iterator last, allocator_v1)
988 {
989 STABLE_VECTOR_CHECK_INVARIANT;
990 difference_type d1 = first - this->cbegin(), d2 = last - this->cbegin();
991 if(d1 != d2){
992 impl_iterator it1(impl.begin() + d1), it2(impl.begin() + d2);
993 for(impl_iterator it = it1; it != it2; ++it)
994 this->delete_node(*it);
995 impl.erase(it1, it2);
996 this->align_nodes(impl.begin() + d1, get_last_align());
997 }
998 return iterator(this->begin() + d1);
999 }
1000
get_last_align()1001 impl_iterator get_last_align()
1002 {
1003 return impl.end() - (ExtraPointers - 1);
1004 }
1005
get_last_align() const1006 const_impl_iterator get_last_align() const
1007 {
1008 return impl.cend() - (ExtraPointers - 1);
1009 }
1010
1011 template<class AllocatorVersion>
priv_erase(const_iterator first,const_iterator last,AllocatorVersion,typename boost::container::containers_detail::enable_if_c<boost::container::containers_detail::is_same<AllocatorVersion,allocator_v2>::value>::type * =0)1012 iterator priv_erase(const_iterator first, const_iterator last, AllocatorVersion,
1013 typename boost::container::containers_detail::enable_if_c
1014 <boost::container::containers_detail::is_same<AllocatorVersion, allocator_v2>
1015 ::value>::type * = 0)
1016 {
1017 STABLE_VECTOR_CHECK_INVARIANT;
1018 return priv_erase(first, last, allocator_v1());
1019 }
1020
node_ptr_cast(void_ptr p)1021 static node_type_ptr_t node_ptr_cast(void_ptr p)
1022 {
1023 using boost::get_pointer;
1024 return node_type_ptr_t(static_cast<node_type_t*>(stable_vector_detail::get_pointer(p)));
1025 }
1026
node_base_ptr_cast(void_ptr p)1027 static node_type_base_ptr_t node_base_ptr_cast(void_ptr p)
1028 {
1029 using boost::get_pointer;
1030 return node_type_base_ptr_t(static_cast<node_type_base_t*>(stable_vector_detail::get_pointer(p)));
1031 }
1032
value(void_ptr p)1033 static value_type& value(void_ptr p)
1034 {
1035 return node_ptr_cast(p)->value;
1036 }
1037
initialize_end_node(size_type impl_capacity=0)1038 void initialize_end_node(size_type impl_capacity = 0)
1039 {
1040 if(impl.empty()){
1041 impl.reserve(impl_capacity + ExtraPointers);
1042 impl.resize (ExtraPointers, void_ptr(0));
1043 impl[0] = &this->internal_data.end_node;
1044 this->internal_data.end_node.up = &impl[0];
1045 }
1046 }
1047
readjust_end_node()1048 void readjust_end_node()
1049 {
1050 if(!this->impl.empty()){
1051 void_ptr &end_node_ref = *(this->get_last_align()-1);
1052 end_node_ref = this->get_end_node();
1053 this->internal_data.end_node.up = &end_node_ref;
1054 }
1055 else{
1056 this->internal_data.end_node.up = void_ptr(&this->internal_data.end_node.up);
1057 }
1058 }
1059
get_end_node() const1060 node_type_ptr_t get_end_node() const
1061 {
1062 const node_type_base_t* cp = &this->internal_data.end_node;
1063 node_type_base_t* p = const_cast<node_type_base_t*>(cp);
1064 return node_ptr_cast(p);
1065 }
1066
1067 template<class Iter>
new_node(void_ptr up,Iter it)1068 void_ptr new_node(void_ptr up, Iter it)
1069 {
1070 node_type_ptr_t p = this->allocate_one();
1071 try{
1072 boost::container::construct_in_place(&*p, it);
1073 p->set_pointer(up);
1074 }
1075 catch(...){
1076 this->deallocate_one(p);
1077 throw;
1078 }
1079 return p;
1080 }
1081
delete_node(void_ptr p)1082 void delete_node(void_ptr p)
1083 {
1084 node_type_ptr_t n(node_ptr_cast(p));
1085 n->~node_type_t();
1086 this->put_in_pool(n);
1087 }
1088
align_nodes(impl_iterator first,impl_iterator last)1089 static void align_nodes(impl_iterator first,impl_iterator last)
1090 {
1091 while(first!=last){
1092 node_ptr_cast(*first)->up = void_ptr(&*first);
1093 ++first;
1094 }
1095 }
1096
insert_not_iter(const_iterator position,size_type n,const T & t)1097 void insert_not_iter(const_iterator position, size_type n, const T& t)
1098 {
1099 typedef constant_iterator<value_type, difference_type> cvalue_iterator;
1100 this->insert_iter(position, cvalue_iterator(t, n), cvalue_iterator(), std::forward_iterator_tag());
1101 }
1102
1103 template <class InputIterator>
insert_iter(const_iterator position,InputIterator first,InputIterator last,boost::mpl::true_)1104 void insert_iter(const_iterator position,InputIterator first,InputIterator last, boost::mpl::true_)
1105 {
1106 typedef typename std::iterator_traits<InputIterator>::iterator_category category;
1107 this->insert_iter(position, first, last, category());
1108 }
1109
1110 template <class InputIterator>
insert_iter(const_iterator position,InputIterator first,InputIterator last,std::input_iterator_tag)1111 void insert_iter(const_iterator position,InputIterator first,InputIterator last,std::input_iterator_tag)
1112 {
1113 for(; first!=last; ++first){
1114 this->insert(position, *first);
1115 }
1116 }
1117
1118 template <class InputIterator>
insert_iter(const_iterator position,InputIterator first,InputIterator last,std::forward_iterator_tag)1119 iterator insert_iter(const_iterator position, InputIterator first, InputIterator last, std::forward_iterator_tag)
1120 {
1121 size_type n = (size_type)std::distance(first,last);
1122 difference_type d = position-this->cbegin();
1123 if(n){
1124 this->insert_iter_prolog(n, d);
1125 const impl_iterator it(impl.begin() + d);
1126 this->insert_iter_fwd(it, first, last, n);
1127 //Fix the pointers for the newly allocated buffer
1128 this->align_nodes(it + n, get_last_align());
1129 }
1130 return this->begin() + d;
1131 }
1132
1133 template <class FwdIterator>
insert_iter_fwd_alloc(const impl_iterator it,FwdIterator first,FwdIterator last,difference_type n,allocator_v1)1134 void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v1)
1135 {
1136 size_type i=0;
1137 try{
1138 while(first!=last){
1139 *(it + i) = this->new_node(void_ptr((void*)(&*(it + i))), first);
1140 ++first;
1141 ++i;
1142 }
1143 }
1144 catch(...){
1145 impl.erase(it + i, it + n);
1146 this->align_nodes(it + i, get_last_align());
1147 throw;
1148 }
1149 }
1150
1151 template <class FwdIterator>
insert_iter_fwd_alloc(const impl_iterator it,FwdIterator first,FwdIterator last,difference_type n,allocator_v2)1152 void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v2)
1153 {
1154 multiallocation_chain mem(get_al().allocate_individual(n));
1155
1156 size_type i = 0;
1157 node_type_ptr_t p = 0;
1158 try{
1159 while(first != last){
1160 p = mem.front();
1161 mem.pop_front();
1162 //This can throw
1163 boost::container::construct_in_place(&*p, first);
1164 p->set_pointer(void_ptr((void*)(&*(it + i))));
1165 ++first;
1166 *(it + i) = p;
1167 ++i;
1168 }
1169 }
1170 catch(...){
1171 get_al().deallocate_one(p);
1172 get_al().deallocate_many(BOOST_CONTAINER_MOVE_NAMESPACE::move(mem));
1173 impl.erase(it+i, it+n);
1174 this->align_nodes(it+i,get_last_align());
1175 throw;
1176 }
1177 }
1178
1179 template <class FwdIterator>
insert_iter_fwd(const impl_iterator it,FwdIterator first,FwdIterator last,difference_type n)1180 void insert_iter_fwd(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n)
1181 {
1182 size_type i = 0;
1183 node_type_ptr_t p = 0;
1184 try{
1185 while(first != last){
1186 p = get_from_pool();
1187 if(!p){
1188 insert_iter_fwd_alloc(it+i, first, last, n-i, alloc_version());
1189 break;
1190 }
1191 //This can throw
1192 boost::container::construct_in_place(&*p, first);
1193 p->set_pointer(void_ptr(&*(it+i)));
1194 ++first;
1195 *(it+i)=p;
1196 ++i;
1197 }
1198 }
1199 catch(...){
1200 put_in_pool(p);
1201 impl.erase(it+i,it+n);
1202 this->align_nodes(it+i,get_last_align());
1203 throw;
1204 }
1205 }
1206
1207 template <class InputIterator>
insert_iter(const_iterator position,InputIterator first,InputIterator last,boost::mpl::false_)1208 void insert_iter(const_iterator position, InputIterator first, InputIterator last, boost::mpl::false_)
1209 {
1210 this->insert_not_iter(position, first, last);
1211 }
1212
swap_impl(stable_vector & x,stable_vector & y)1213 static void swap_impl(stable_vector& x,stable_vector& y)
1214 {
1215 using std::swap;
1216 swap(x.get_al(),y.get_al());
1217 swap(x.impl,y.impl);
1218 swap(x.internal_data.pool_size, y.internal_data.pool_size);
1219 x.readjust_end_node();
1220 y.readjust_end_node();
1221 }
1222
1223 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
invariant() const1224 bool invariant()const
1225 {
1226 if(impl.empty())
1227 return !capacity() && !size();
1228 if(get_end_node() != *(impl.end() - ExtraPointers)){
1229 return false;
1230 }
1231 for(const_impl_iterator it=impl.begin(),it_end=get_last_align();it!=it_end;++it){
1232 if(node_ptr_cast(*it)->up != &*it)
1233 return false;
1234 }
1235 size_type n = capacity()-size();
1236 const void_ptr &pool_head = impl.back();
1237 size_type num_pool = 0;
1238 node_type_ptr_t p = node_ptr_cast(pool_head);
1239 while(p){
1240 ++num_pool;
1241 p = p->up;
1242 }
1243 return n >= num_pool;
1244 }
1245
1246 class invariant_checker:private boost::noncopyable
1247 {
1248 const stable_vector* p;
1249 public:
invariant_checker(const stable_vector & v)1250 invariant_checker(const stable_vector& v):p(&v){}
~invariant_checker()1251 ~invariant_checker(){BOOST_ASSERT(p->invariant());}
touch()1252 void touch(){}
1253 };
1254 #endif
1255
1256 struct ebo_holder
1257 : node_allocator_type
1258 {
ebo_holderboost::container::stable_vector::ebo_holder1259 ebo_holder(const allocator_type &a)
1260 : node_allocator_type(a), pool_size(0), end_node()
1261 {
1262 end_node.set_pointer(void_ptr(&end_node.up));
1263 }
1264 size_type pool_size;
1265 node_type_base_t end_node;
1266 } internal_data;
1267
get_al()1268 node_allocator_type &get_al() { return internal_data; }
get_al() const1269 const node_allocator_type &get_al() const { return internal_data; }
1270
1271 impl_type impl;
1272 /// @endcond
1273 };
1274
1275 template <typename T,typename Allocator>
operator ==(const stable_vector<T,Allocator> & x,const stable_vector<T,Allocator> & y)1276 bool operator==(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1277 {
1278 return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
1279 }
1280
1281 template <typename T,typename Allocator>
operator <(const stable_vector<T,Allocator> & x,const stable_vector<T,Allocator> & y)1282 bool operator< (const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1283 {
1284 return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
1285 }
1286
1287 template <typename T,typename Allocator>
operator !=(const stable_vector<T,Allocator> & x,const stable_vector<T,Allocator> & y)1288 bool operator!=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1289 {
1290 return !(x==y);
1291 }
1292
1293 template <typename T,typename Allocator>
operator >(const stable_vector<T,Allocator> & x,const stable_vector<T,Allocator> & y)1294 bool operator> (const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1295 {
1296 return y<x;
1297 }
1298
1299 template <typename T,typename Allocator>
operator >=(const stable_vector<T,Allocator> & x,const stable_vector<T,Allocator> & y)1300 bool operator>=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1301 {
1302 return !(x<y);
1303 }
1304
1305 template <typename T,typename Allocator>
operator <=(const stable_vector<T,Allocator> & x,const stable_vector<T,Allocator> & y)1306 bool operator<=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1307 {
1308 return !(x>y);
1309 }
1310
1311 // specialized algorithms:
1312
1313 template <typename T, typename Allocator>
swap(stable_vector<T,Allocator> & x,stable_vector<T,Allocator> & y)1314 void swap(stable_vector<T,Allocator>& x,stable_vector<T,Allocator>& y)
1315 {
1316 x.swap(y);
1317 }
1318
1319 /// @cond
1320
1321 #undef STABLE_VECTOR_CHECK_INVARIANT
1322
1323 /// @endcond
1324
1325 }}
1326
1327 #include INCLUDE_BOOST_CONTAINER_DETAIL_CONFIG_END_HPP
1328
1329 #endif //BOOST_CONTAINER_STABLE_VECTOR_HPP
1330