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