comparison DEPENDENCIES/generic/include/boost/container/stable_vector.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2008-2012. 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
19 #ifndef BOOST_CONTAINER_STABLE_VECTOR_HPP
20 #define BOOST_CONTAINER_STABLE_VECTOR_HPP
21
22 #if defined(_MSC_VER)
23 # pragma once
24 #endif
25
26 #include <boost/container/detail/config_begin.hpp>
27 #include <boost/container/detail/workaround.hpp>
28 #include <boost/container/container_fwd.hpp>
29 #include <boost/mpl/bool.hpp>
30 #include <boost/mpl/not.hpp>
31 #include <boost/assert.hpp>
32 #include <boost/container/throw_exception.hpp>
33 #include <boost/container/detail/allocator_version_traits.hpp>
34 #include <boost/container/detail/utilities.hpp>
35 #include <boost/container/detail/iterators.hpp>
36 #include <boost/container/detail/algorithms.hpp>
37 #include <boost/container/allocator_traits.hpp>
38 #include <boost/container/throw_exception.hpp>
39 #include <boost/intrusive/pointer_traits.hpp>
40 #include <boost/detail/no_exceptions_support.hpp>
41 #include <boost/aligned_storage.hpp>
42 #include <boost/move/utility.hpp>
43 #include <boost/move/iterator.hpp>
44 #include <boost/move/detail/move_helpers.hpp>
45 #include <algorithm> //max
46
47 #include <memory>
48 #include <new> //placement new
49
50 ///@cond
51
52 #include <boost/container/vector.hpp>
53
54 //#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
55
56 ///@endcond
57
58 namespace boost {
59 namespace container {
60
61 ///@cond
62
63 namespace stable_vector_detail{
64
65 template <class C>
66 class clear_on_destroy
67 {
68 public:
69 clear_on_destroy(C &c)
70 : c_(c), do_clear_(true)
71 {}
72
73 void release()
74 { do_clear_ = false; }
75
76 ~clear_on_destroy()
77 {
78 if(do_clear_){
79 c_.clear();
80 c_.priv_clear_pool();
81 }
82 }
83
84 private:
85 clear_on_destroy(const clear_on_destroy &);
86 clear_on_destroy &operator=(const clear_on_destroy &);
87 C &c_;
88 bool do_clear_;
89 };
90
91 template<typename Pointer>
92 struct node;
93
94 template<class VoidPtr>
95 struct node_base
96 {
97 private:
98 typedef typename boost::intrusive::
99 pointer_traits<VoidPtr> void_ptr_traits;
100 typedef typename void_ptr_traits::
101 template rebind_pointer
102 <node_base>::type node_base_ptr;
103 typedef typename void_ptr_traits::
104 template rebind_pointer
105 <node_base_ptr>::type node_base_ptr_ptr;
106
107 public:
108 node_base(const node_base_ptr_ptr &n)
109 : up(n)
110 {}
111
112 node_base()
113 : up()
114 {}
115
116 node_base_ptr_ptr up;
117 };
118
119 template<typename Pointer>
120 struct node
121 : public node_base
122 <typename ::boost::intrusive::pointer_traits<Pointer>::template
123 rebind_pointer<void>::type
124 >
125 {
126 // private:
127 // node();
128
129 public:
130 typename ::boost::intrusive::pointer_traits<Pointer>::element_type value;
131 };
132
133 template<typename Pointer, bool IsConst>
134 class iterator
135 {
136 typedef boost::intrusive::pointer_traits<Pointer> non_const_ptr_traits;
137 public:
138 typedef std::random_access_iterator_tag iterator_category;
139 typedef typename non_const_ptr_traits::element_type value_type;
140 typedef typename non_const_ptr_traits::difference_type difference_type;
141 typedef typename ::boost::container::container_detail::if_c
142 < IsConst
143 , typename non_const_ptr_traits::template
144 rebind_pointer<const value_type>::type
145 , Pointer
146 >::type pointer;
147 typedef typename ::boost::container::container_detail::if_c
148 < IsConst
149 , const value_type&
150 , value_type&
151 >::type reference;
152
153 private:
154 typedef typename non_const_ptr_traits::template
155 rebind_pointer<void>::type void_ptr;
156 typedef node<Pointer> node_type;
157 typedef node_base<void_ptr> node_base_type;
158 typedef typename non_const_ptr_traits::template
159 rebind_pointer<node_type>::type node_ptr;
160 typedef boost::intrusive::
161 pointer_traits<node_ptr> node_ptr_traits;
162 typedef typename non_const_ptr_traits::template
163 rebind_pointer<node_base_type>::type node_base_ptr;
164 typedef typename non_const_ptr_traits::template
165 rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
166
167 node_ptr m_pn;
168
169 public:
170
171 explicit iterator(node_ptr p) BOOST_CONTAINER_NOEXCEPT
172 : m_pn(p)
173 {}
174
175 iterator() BOOST_CONTAINER_NOEXCEPT
176 {}
177
178 iterator(iterator<Pointer, false> const& other) BOOST_CONTAINER_NOEXCEPT
179 : m_pn(other.node_pointer())
180 {}
181
182 node_ptr &node_pointer() BOOST_CONTAINER_NOEXCEPT
183 { return m_pn; }
184
185 const node_ptr &node_pointer() const BOOST_CONTAINER_NOEXCEPT
186 { return m_pn; }
187
188 public:
189 //Pointer like operators
190 reference operator*() const BOOST_CONTAINER_NOEXCEPT
191 { return m_pn->value; }
192
193 pointer operator->() const BOOST_CONTAINER_NOEXCEPT
194 {
195 typedef boost::intrusive::pointer_traits<pointer> ptr_traits;
196 return ptr_traits::pointer_to(this->operator*());
197 }
198
199 //Increment / Decrement
200 iterator& operator++() BOOST_CONTAINER_NOEXCEPT
201 {
202 if(node_base_ptr_ptr p = this->m_pn->up){
203 ++p;
204 this->m_pn = node_ptr_traits::static_cast_from(*p);
205 }
206 return *this;
207 }
208
209 iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
210 { iterator tmp(*this); ++*this; return iterator(tmp); }
211
212 iterator& operator--() BOOST_CONTAINER_NOEXCEPT
213 {
214 if(node_base_ptr_ptr p = this->m_pn->up){
215 --p;
216 this->m_pn = node_ptr_traits::static_cast_from(*p);
217 }
218 return *this;
219 }
220
221 iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
222 { iterator tmp(*this); --*this; return iterator(tmp); }
223
224 reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT
225 {
226 iterator tmp(*this);
227 tmp += off;
228 return *tmp;
229 }
230
231 iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT
232 {
233 if(node_base_ptr_ptr p = this->m_pn->up){
234 p += off;
235 this->m_pn = node_ptr_traits::static_cast_from(*p);
236 }
237 return *this;
238 }
239
240 friend iterator operator+(const iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT
241 {
242 iterator tmp(left);
243 tmp += off;
244 return tmp;
245 }
246
247 friend iterator operator+(difference_type off, const iterator& right) BOOST_CONTAINER_NOEXCEPT
248 {
249 iterator tmp(right);
250 tmp += off;
251 return tmp;
252 }
253
254 iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT
255 { *this += -off; return *this; }
256
257 friend iterator operator-(const iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT
258 {
259 iterator tmp(left);
260 tmp -= off;
261 return tmp;
262 }
263
264 friend difference_type operator-(const iterator& left, const iterator& right) BOOST_CONTAINER_NOEXCEPT
265 { return left.m_pn->up - right.m_pn->up; }
266
267 //Comparison operators
268 friend bool operator== (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
269 { return l.m_pn == r.m_pn; }
270
271 friend bool operator!= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
272 { return l.m_pn != r.m_pn; }
273
274 friend bool operator< (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
275 { return l.m_pn->up < r.m_pn->up; }
276
277 friend bool operator<= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
278 { return l.m_pn->up <= r.m_pn->up; }
279
280 friend bool operator> (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
281 { return l.m_pn->up > r.m_pn->up; }
282
283 friend bool operator>= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
284 { return l.m_pn->up >= r.m_pn->up; }
285 };
286
287 template<class VoidPtr, class VoidAllocator>
288 struct index_traits
289 {
290 typedef boost::intrusive::
291 pointer_traits
292 <VoidPtr> void_ptr_traits;
293 typedef stable_vector_detail::
294 node_base<VoidPtr> node_base_type;
295 typedef typename void_ptr_traits::template
296 rebind_pointer<node_base_type>::type node_base_ptr;
297 typedef typename void_ptr_traits::template
298 rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
299 typedef boost::intrusive::
300 pointer_traits<node_base_ptr> node_base_ptr_traits;
301 typedef boost::intrusive::
302 pointer_traits<node_base_ptr_ptr> node_base_ptr_ptr_traits;
303 typedef typename allocator_traits<VoidAllocator>::
304 template portable_rebind_alloc
305 <node_base_ptr>::type node_base_ptr_allocator;
306 typedef ::boost::container::vector
307 <node_base_ptr, node_base_ptr_allocator> index_type;
308 typedef typename index_type::iterator index_iterator;
309 typedef typename index_type::const_iterator const_index_iterator;
310 typedef typename index_type::size_type size_type;
311
312 static const size_type ExtraPointers = 3;
313 //Stable vector stores metadata at the end of the index (node_base_ptr vector) with additional 3 pointers:
314 // back() is this->index.back() - ExtraPointers;
315 // end node index is *(this->index.end() - 3)
316 // Node cache first is *(this->index.end() - 2);
317 // Node cache last is this->index.back();
318
319 static node_base_ptr_ptr ptr_to_node_base_ptr(node_base_ptr &n)
320 { return node_base_ptr_ptr_traits::pointer_to(n); }
321
322 static void fix_up_pointers(index_iterator first, index_iterator last)
323 {
324 while(first != last){
325 typedef typename index_type::reference node_base_ptr_ref;
326 node_base_ptr_ref nbp = *first;
327 nbp->up = index_traits::ptr_to_node_base_ptr(nbp);
328 ++first;
329 }
330 }
331
332 static index_iterator get_fix_up_end(index_type &index)
333 { return index.end() - (ExtraPointers - 1); }
334
335 static void fix_up_pointers_from(index_type & index, index_iterator first)
336 { index_traits::fix_up_pointers(first, index_traits::get_fix_up_end(index)); }
337
338 static void readjust_end_node(index_type &index, node_base_type &end_node)
339 {
340 if(!index.empty()){
341 index_iterator end_node_it(index_traits::get_fix_up_end(index));
342 node_base_ptr &end_node_idx_ref = *(--end_node_it);
343 end_node_idx_ref = node_base_ptr_traits::pointer_to(end_node);
344 end_node.up = node_base_ptr_ptr_traits::pointer_to(end_node_idx_ref);
345 }
346 else{
347 end_node.up = node_base_ptr_ptr();
348 }
349 }
350
351 static void initialize_end_node(index_type &index, node_base_type &end_node, const size_type index_capacity_if_empty)
352 {
353 if(index.empty()){
354 index.reserve(index_capacity_if_empty + ExtraPointers);
355 index.resize(ExtraPointers);
356 node_base_ptr &end_node_ref = *index.data();
357 end_node_ref = node_base_ptr_traits::pointer_to(end_node);
358 end_node.up = index_traits::ptr_to_node_base_ptr(end_node_ref);
359 }
360 }
361
362 #ifdef STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
363 static bool invariants(index_type &index)
364 {
365 for( index_iterator it = index.begin()
366 , it_end = index_traits::get_fix_up_end(index)
367 ; it != it_end
368 ; ++it){
369 if((*it)->up != index_traits::ptr_to_node_base_ptr(*it)){
370 return false;
371 }
372 }
373 return true;
374 }
375 #endif //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
376 };
377
378 } //namespace stable_vector_detail
379
380 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
381
382 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
383
384 #define STABLE_VECTOR_CHECK_INVARIANT \
385 invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \
386 BOOST_JOIN(check_invariant_,__LINE__).touch();
387
388 #else //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
389
390 #define STABLE_VECTOR_CHECK_INVARIANT
391
392 #endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
393
394 #endif //#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
395
396 /// @endcond
397
398 //! Originally developed by Joaquin M. Lopez Munoz, stable_vector is a std::vector
399 //! drop-in replacement implemented as a node container, offering iterator and reference
400 //! stability.
401 //!
402 //! Here are the details taken from the author's blog
403 //! (<a href="http://bannalia.blogspot.com/2008/09/introducing-stablevector.html" >
404 //! Introducing stable_vector</a>):
405 //!
406 //! We present stable_vector, a fully STL-compliant stable container that provides
407 //! most of the features of std::vector except element contiguity.
408 //!
409 //! General properties: stable_vector satisfies all the requirements of a container,
410 //! a reversible container and a sequence and provides all the optional operations
411 //! present in std::vector. Like std::vector, iterators are random access.
412 //! stable_vector does not provide element contiguity; in exchange for this absence,
413 //! the container is stable, i.e. references and iterators to an element of a stable_vector
414 //! remain valid as long as the element is not erased, and an iterator that has been
415 //! assigned the return value of end() always remain valid until the destruction of
416 //! the associated stable_vector.
417 //!
418 //! Operation complexity: The big-O complexities of stable_vector operations match
419 //! exactly those of std::vector. In general, insertion/deletion is constant time at
420 //! the end of the sequence and linear elsewhere. Unlike std::vector, stable_vector
421 //! does not internally perform any value_type destruction, copy or assignment
422 //! operations other than those exactly corresponding to the insertion of new
423 //! elements or deletion of stored elements, which can sometimes compensate in terms
424 //! of performance for the extra burden of doing more pointer manipulation and an
425 //! additional allocation per element.
426 //!
427 //! Exception safety: As stable_vector does not internally copy elements around, some
428 //! operations provide stronger exception safety guarantees than in std::vector.
429 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
430 template <class T, class Allocator = std::allocator<T> >
431 #else
432 template <class T, class Allocator>
433 #endif
434 class stable_vector
435 {
436 ///@cond
437 typedef allocator_traits<Allocator> allocator_traits_type;
438 typedef boost::intrusive::
439 pointer_traits
440 <typename allocator_traits_type::pointer> ptr_traits;
441 typedef typename ptr_traits::
442 template rebind_pointer<void>::type void_ptr;
443 typedef typename allocator_traits_type::
444 template portable_rebind_alloc
445 <void>::type void_allocator_type;
446 typedef stable_vector_detail::index_traits
447 <void_ptr, void_allocator_type> index_traits_type;
448 typedef typename index_traits_type::node_base_type node_base_type;
449 typedef typename index_traits_type::node_base_ptr node_base_ptr;
450 typedef typename index_traits_type::
451 node_base_ptr_ptr node_base_ptr_ptr;
452 typedef typename index_traits_type::
453 node_base_ptr_traits node_base_ptr_traits;
454 typedef typename index_traits_type::
455 node_base_ptr_ptr_traits node_base_ptr_ptr_traits;
456 typedef typename index_traits_type::index_type index_type;
457 typedef typename index_traits_type::index_iterator index_iterator;
458 typedef typename index_traits_type::
459 const_index_iterator const_index_iterator;
460 typedef stable_vector_detail::node
461 <typename ptr_traits::pointer> node_type;
462 typedef typename ptr_traits::template
463 rebind_pointer<node_type>::type node_ptr;
464 typedef boost::intrusive::
465 pointer_traits<node_ptr> node_ptr_traits;
466 typedef typename ptr_traits::template
467 rebind_pointer<const node_type>::type const_node_ptr;
468 typedef boost::intrusive::
469 pointer_traits<const_node_ptr> const_node_ptr_traits;
470 typedef typename node_ptr_traits::reference node_reference;
471 typedef typename const_node_ptr_traits::reference const_node_reference;
472
473 typedef ::boost::container::container_detail::
474 integral_constant<unsigned, 1> allocator_v1;
475 typedef ::boost::container::container_detail::
476 integral_constant<unsigned, 2> allocator_v2;
477 typedef ::boost::container::container_detail::integral_constant
478 <unsigned, boost::container::container_detail::
479 version<Allocator>::value> alloc_version;
480 typedef typename allocator_traits_type::
481 template portable_rebind_alloc
482 <node_type>::type node_allocator_type;
483
484 typedef ::boost::container::container_detail::
485 allocator_version_traits<node_allocator_type> allocator_version_traits_t;
486 typedef typename allocator_version_traits_t::multiallocation_chain multiallocation_chain;
487
488 node_ptr allocate_one()
489 { return allocator_version_traits_t::allocate_one(this->priv_node_alloc()); }
490
491 void deallocate_one(const node_ptr &p)
492 { allocator_version_traits_t::deallocate_one(this->priv_node_alloc(), p); }
493
494 void allocate_individual(typename allocator_traits_type::size_type n, multiallocation_chain &m)
495 { allocator_version_traits_t::allocate_individual(this->priv_node_alloc(), n, m); }
496
497 void deallocate_individual(multiallocation_chain &holder)
498 { allocator_version_traits_t::deallocate_individual(this->priv_node_alloc(), holder); }
499
500 friend class stable_vector_detail::clear_on_destroy<stable_vector>;
501 typedef stable_vector_detail::iterator
502 < typename allocator_traits<Allocator>::pointer
503 , false> iterator_impl;
504 typedef stable_vector_detail::iterator
505 < typename allocator_traits<Allocator>::pointer
506 , false> const_iterator_impl;
507 ///@endcond
508 public:
509
510 //////////////////////////////////////////////
511 //
512 // types
513 //
514 //////////////////////////////////////////////
515 typedef T value_type;
516 typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
517 typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
518 typedef typename ::boost::container::allocator_traits<Allocator>::reference reference;
519 typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
520 typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
521 typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
522 typedef Allocator allocator_type;
523 typedef node_allocator_type stored_allocator_type;
524 typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
525 typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
526 typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<iterator>) reverse_iterator;
527 typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<const_iterator>) const_reverse_iterator;
528
529 ///@cond
530 private:
531 BOOST_COPYABLE_AND_MOVABLE(stable_vector)
532 static const size_type ExtraPointers = index_traits_type::ExtraPointers;
533
534 class insert_rollback;
535 friend class insert_rollback;
536
537 class push_back_rollback;
538 friend class push_back_rollback;
539 ///@endcond
540
541 public:
542 //////////////////////////////////////////////
543 //
544 // construct/copy/destroy
545 //
546 //////////////////////////////////////////////
547
548 //! <b>Effects</b>: Default constructs a stable_vector.
549 //!
550 //! <b>Throws</b>: If allocator_type's default constructor throws.
551 //!
552 //! <b>Complexity</b>: Constant.
553 stable_vector()
554 : internal_data(), index()
555 {
556 STABLE_VECTOR_CHECK_INVARIANT;
557 }
558
559 //! <b>Effects</b>: Constructs a stable_vector taking the allocator as parameter.
560 //!
561 //! <b>Throws</b>: Nothing
562 //!
563 //! <b>Complexity</b>: Constant.
564 explicit stable_vector(const allocator_type& al) BOOST_CONTAINER_NOEXCEPT
565 : internal_data(al), index(al)
566 {
567 STABLE_VECTOR_CHECK_INVARIANT;
568 }
569
570 //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
571 //! and inserts n value initialized values.
572 //!
573 //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
574 //! throws or T's default or copy constructor throws.
575 //!
576 //! <b>Complexity</b>: Linear to n.
577 explicit stable_vector(size_type n)
578 : internal_data(), index()
579 {
580 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
581 this->resize(n);
582 STABLE_VECTOR_CHECK_INVARIANT;
583 cod.release();
584 }
585
586 //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
587 //! and inserts n default initialized values.
588 //!
589 //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
590 //! throws or T's default or copy constructor throws.
591 //!
592 //! <b>Complexity</b>: Linear to n.
593 //!
594 //! <b>Note</b>: Non-standard extension
595 stable_vector(size_type n, default_init_t)
596 : internal_data(), index()
597 {
598 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
599 this->resize(n, default_init);
600 STABLE_VECTOR_CHECK_INVARIANT;
601 cod.release();
602 }
603
604 //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
605 //! and inserts n copies of value.
606 //!
607 //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
608 //! throws or T's default or copy constructor throws.
609 //!
610 //! <b>Complexity</b>: Linear to n.
611 stable_vector(size_type n, const T& t, const allocator_type& al = allocator_type())
612 : internal_data(al), index(al)
613 {
614 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
615 this->insert(this->cend(), n, t);
616 STABLE_VECTOR_CHECK_INVARIANT;
617 cod.release();
618 }
619
620 //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
621 //! and inserts a copy of the range [first, last) in the stable_vector.
622 //!
623 //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
624 //! throws or T's constructor taking an dereferenced InIt throws.
625 //!
626 //! <b>Complexity</b>: Linear to the range [first, last).
627 template <class InputIterator>
628 stable_vector(InputIterator first,InputIterator last, const allocator_type& al = allocator_type())
629 : internal_data(al), index(al)
630 {
631 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
632 this->insert(this->cend(), first, last);
633 STABLE_VECTOR_CHECK_INVARIANT;
634 cod.release();
635 }
636
637 //! <b>Effects</b>: Copy constructs a stable_vector.
638 //!
639 //! <b>Postcondition</b>: x == *this.
640 //!
641 //! <b>Complexity</b>: Linear to the elements x contains.
642 stable_vector(const stable_vector& x)
643 : internal_data(allocator_traits<node_allocator_type>::
644 select_on_container_copy_construction(x.priv_node_alloc()))
645 , index(allocator_traits<allocator_type>::
646 select_on_container_copy_construction(x.index.get_stored_allocator()))
647 {
648 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
649 this->insert(this->cend(), x.begin(), x.end());
650 STABLE_VECTOR_CHECK_INVARIANT;
651 cod.release();
652 }
653
654 //! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
655 //!
656 //! <b>Throws</b>: If allocator_type's copy constructor throws.
657 //!
658 //! <b>Complexity</b>: Constant.
659 stable_vector(BOOST_RV_REF(stable_vector) x)
660 : internal_data(boost::move(x.priv_node_alloc())), index(boost::move(x.index))
661 {
662 this->priv_swap_members(x);
663 }
664
665 //! <b>Effects</b>: Copy constructs a stable_vector using the specified allocator.
666 //!
667 //! <b>Postcondition</b>: x == *this.
668 //!
669 //! <b>Complexity</b>: Linear to the elements x contains.
670 stable_vector(const stable_vector& x, const allocator_type &a)
671 : internal_data(a), index(a)
672 {
673 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
674 this->insert(this->cend(), x.begin(), x.end());
675 STABLE_VECTOR_CHECK_INVARIANT;
676 cod.release();
677 }
678
679 //! <b>Effects</b>: Move constructor using the specified allocator.
680 //! Moves mx's resources to *this.
681 //!
682 //! <b>Throws</b>: If allocator_type's copy constructor throws.
683 //!
684 //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise
685 stable_vector(BOOST_RV_REF(stable_vector) x, const allocator_type &a)
686 : internal_data(a), index(a)
687 {
688 if(this->priv_node_alloc() == x.priv_node_alloc()){
689 this->priv_swap_members(x);
690 }
691 else{
692 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
693 this->insert(this->cend(), x.begin(), x.end());
694 STABLE_VECTOR_CHECK_INVARIANT;
695 cod.release();
696 }
697 }
698
699 //! <b>Effects</b>: Destroys the stable_vector. All stored values are destroyed
700 //! and used memory is deallocated.
701 //!
702 //! <b>Throws</b>: Nothing.
703 //!
704 //! <b>Complexity</b>: Linear to the number of elements.
705 ~stable_vector()
706 {
707 this->clear();
708 this->priv_clear_pool();
709 }
710
711 //! <b>Effects</b>: Makes *this contain the same elements as x.
712 //!
713 //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
714 //! of each of x's elements.
715 //!
716 //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
717 //!
718 //! <b>Complexity</b>: Linear to the number of elements in x.
719 stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
720 {
721 STABLE_VECTOR_CHECK_INVARIANT;
722 if (&x != this){
723 node_allocator_type &this_alloc = this->priv_node_alloc();
724 const node_allocator_type &x_alloc = x.priv_node_alloc();
725 container_detail::bool_<allocator_traits_type::
726 propagate_on_container_copy_assignment::value> flag;
727 if(flag && this_alloc != x_alloc){
728 this->clear();
729 this->shrink_to_fit();
730 }
731 container_detail::assign_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
732 container_detail::assign_alloc(this->index.get_stored_allocator(), x.index.get_stored_allocator(), flag);
733 this->assign(x.begin(), x.end());
734 }
735 return *this;
736 }
737
738 //! <b>Effects</b>: Move assignment. All mx's values are transferred to *this.
739 //!
740 //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
741 //! before the function.
742 //!
743 //! <b>Throws</b>: If allocator_type's copy constructor throws.
744 //!
745 //! <b>Complexity</b>: Linear.
746 stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
747 {
748 if (&x != this){
749 node_allocator_type &this_alloc = this->priv_node_alloc();
750 node_allocator_type &x_alloc = x.priv_node_alloc();
751 //If allocators are equal we can just swap pointers
752 if(this_alloc == x_alloc){
753 //Destroy objects but retain memory
754 this->clear();
755 this->index = boost::move(x.index);
756 this->priv_swap_members(x);
757 //Move allocator if needed
758 container_detail::bool_<allocator_traits_type::
759 propagate_on_container_move_assignment::value> flag;
760 container_detail::move_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
761 }
762 //If unequal allocators, then do a one by one move
763 else{
764 this->assign( boost::make_move_iterator(x.begin())
765 , boost::make_move_iterator(x.end()));
766 }
767 }
768 return *this;
769 }
770
771
772 //! <b>Effects</b>: Assigns the n copies of val to *this.
773 //!
774 //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
775 //!
776 //! <b>Complexity</b>: Linear to n.
777 void assign(size_type n, const T& t)
778 {
779 typedef constant_iterator<value_type, difference_type> cvalue_iterator;
780 this->assign(cvalue_iterator(t, n), cvalue_iterator());
781 }
782
783 //! <b>Effects</b>: Assigns the the range [first, last) to *this.
784 //!
785 //! <b>Throws</b>: If memory allocation throws or
786 //! T's constructor from dereferencing InpIt throws.
787 //!
788 //! <b>Complexity</b>: Linear to n.
789 template<typename InputIterator>
790 void assign(InputIterator first,InputIterator last
791 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
792 , typename container_detail::enable_if_c
793 < !container_detail::is_convertible<InputIterator, size_type>::value
794 >::type * = 0
795 #endif
796 )
797 {
798 STABLE_VECTOR_CHECK_INVARIANT;
799 iterator first1 = this->begin();
800 iterator last1 = this->end();
801 for ( ; first1 != last1 && first != last; ++first1, ++first)
802 *first1 = *first;
803 if (first == last){
804 this->erase(first1, last1);
805 }
806 else{
807 this->insert(last1, first, last);
808 }
809 }
810
811 //! <b>Effects</b>: Returns a copy of the internal allocator.
812 //!
813 //! <b>Throws</b>: If allocator's copy constructor throws.
814 //!
815 //! <b>Complexity</b>: Constant.
816 allocator_type get_allocator() const
817 { return this->priv_node_alloc(); }
818
819 //! <b>Effects</b>: Returns a reference to the internal allocator.
820 //!
821 //! <b>Throws</b>: Nothing
822 //!
823 //! <b>Complexity</b>: Constant.
824 //!
825 //! <b>Note</b>: Non-standard extension.
826 const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
827 { return this->priv_node_alloc(); }
828
829 //! <b>Effects</b>: Returns a reference to the internal allocator.
830 //!
831 //! <b>Throws</b>: Nothing
832 //!
833 //! <b>Complexity</b>: Constant.
834 //!
835 //! <b>Note</b>: Non-standard extension.
836 stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
837 { return this->priv_node_alloc(); }
838
839 //////////////////////////////////////////////
840 //
841 // iterators
842 //
843 //////////////////////////////////////////////
844
845 //! <b>Effects</b>: Returns an iterator to the first element contained in the stable_vector.
846 //!
847 //! <b>Throws</b>: Nothing.
848 //!
849 //! <b>Complexity</b>: Constant.
850 iterator begin() BOOST_CONTAINER_NOEXCEPT
851 { return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); }
852
853 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
854 //!
855 //! <b>Throws</b>: Nothing.
856 //!
857 //! <b>Complexity</b>: Constant.
858 const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
859 { return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; }
860
861 //! <b>Effects</b>: Returns an iterator to the end of the stable_vector.
862 //!
863 //! <b>Throws</b>: Nothing.
864 //!
865 //! <b>Complexity</b>: Constant.
866 iterator end() BOOST_CONTAINER_NOEXCEPT
867 { return iterator(this->priv_get_end_node()); }
868
869 //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
870 //!
871 //! <b>Throws</b>: Nothing.
872 //!
873 //! <b>Complexity</b>: Constant.
874 const_iterator end() const BOOST_CONTAINER_NOEXCEPT
875 { return const_iterator(this->priv_get_end_node()); }
876
877 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
878 //! of the reversed stable_vector.
879 //!
880 //! <b>Throws</b>: Nothing.
881 //!
882 //! <b>Complexity</b>: Constant.
883 reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
884 { return reverse_iterator(this->end()); }
885
886 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
887 //! of the reversed stable_vector.
888 //!
889 //! <b>Throws</b>: Nothing.
890 //!
891 //! <b>Complexity</b>: Constant.
892 const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
893 { return const_reverse_iterator(this->end()); }
894
895 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
896 //! of the reversed stable_vector.
897 //!
898 //! <b>Throws</b>: Nothing.
899 //!
900 //! <b>Complexity</b>: Constant.
901 reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
902 { return reverse_iterator(this->begin()); }
903
904 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
905 //! of the reversed stable_vector.
906 //!
907 //! <b>Throws</b>: Nothing.
908 //!
909 //! <b>Complexity</b>: Constant.
910 const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
911 { return const_reverse_iterator(this->begin()); }
912
913 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
914 //!
915 //! <b>Throws</b>: Nothing.
916 //!
917 //! <b>Complexity</b>: Constant.
918 const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
919 { return this->begin(); }
920
921 //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
922 //!
923 //! <b>Throws</b>: Nothing.
924 //!
925 //! <b>Complexity</b>: Constant.
926 const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
927 { return this->end(); }
928
929 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
930 //! of the reversed stable_vector.
931 //!
932 //! <b>Throws</b>: Nothing.
933 //!
934 //! <b>Complexity</b>: Constant.
935 const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
936 { return this->rbegin(); }
937
938 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
939 //! of the reversed stable_vector.
940 //!
941 //! <b>Throws</b>: Nothing.
942 //!
943 //! <b>Complexity</b>: Constant.
944 const_reverse_iterator crend()const BOOST_CONTAINER_NOEXCEPT
945 { return this->rend(); }
946
947 //////////////////////////////////////////////
948 //
949 // capacity
950 //
951 //////////////////////////////////////////////
952
953 //! <b>Effects</b>: Returns true if the stable_vector contains no elements.
954 //!
955 //! <b>Throws</b>: Nothing.
956 //!
957 //! <b>Complexity</b>: Constant.
958 bool empty() const BOOST_CONTAINER_NOEXCEPT
959 { return this->index.size() <= ExtraPointers; }
960
961 //! <b>Effects</b>: Returns the number of the elements contained in the stable_vector.
962 //!
963 //! <b>Throws</b>: Nothing.
964 //!
965 //! <b>Complexity</b>: Constant.
966 size_type size() const BOOST_CONTAINER_NOEXCEPT
967 {
968 const size_type index_size = this->index.size();
969 return (index_size - ExtraPointers) & (std::size_t(0u) -std::size_t(index_size != 0));
970 }
971
972 //! <b>Effects</b>: Returns the largest possible size of the stable_vector.
973 //!
974 //! <b>Throws</b>: Nothing.
975 //!
976 //! <b>Complexity</b>: Constant.
977 size_type max_size() const BOOST_CONTAINER_NOEXCEPT
978 { return this->index.max_size() - ExtraPointers; }
979
980 //! <b>Effects</b>: Inserts or erases elements at the end such that
981 //! the size becomes n. New elements are value initialized.
982 //!
983 //! <b>Throws</b>: If memory allocation throws, or T's default constructor throws.
984 //!
985 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
986 void resize(size_type n)
987 {
988 typedef value_init_construct_iterator<value_type, difference_type> value_init_iterator;
989 STABLE_VECTOR_CHECK_INVARIANT;
990 if(n > this->size())
991 this->insert(this->cend(), value_init_iterator(n - this->size()), value_init_iterator());
992 else if(n < this->size())
993 this->erase(this->cbegin() + n, this->cend());
994 }
995
996 //! <b>Effects</b>: Inserts or erases elements at the end such that
997 //! the size becomes n. New elements are default initialized.
998 //!
999 //! <b>Throws</b>: If memory allocation throws, or T's default constructor throws.
1000 //!
1001 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1002 //!
1003 //! <b>Note</b>: Non-standard extension
1004 void resize(size_type n, default_init_t)
1005 {
1006 typedef default_init_construct_iterator<value_type, difference_type> default_init_iterator;
1007 STABLE_VECTOR_CHECK_INVARIANT;
1008 if(n > this->size())
1009 this->insert(this->cend(), default_init_iterator(n - this->size()), default_init_iterator());
1010 else if(n < this->size())
1011 this->erase(this->cbegin() + n, this->cend());
1012 }
1013
1014 //! <b>Effects</b>: Inserts or erases elements at the end such that
1015 //! the size becomes n. New elements are copy constructed from x.
1016 //!
1017 //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
1018 //!
1019 //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1020 void resize(size_type n, const T& t)
1021 {
1022 STABLE_VECTOR_CHECK_INVARIANT;
1023 if(n > this->size())
1024 this->insert(this->cend(), n - this->size(), t);
1025 else if(n < this->size())
1026 this->erase(this->cbegin() + n, this->cend());
1027 }
1028
1029 //! <b>Effects</b>: Number of elements for which memory has been allocated.
1030 //! capacity() is always greater than or equal to size().
1031 //!
1032 //! <b>Throws</b>: Nothing.
1033 //!
1034 //! <b>Complexity</b>: Constant.
1035 size_type capacity() const BOOST_CONTAINER_NOEXCEPT
1036 {
1037 const size_type index_size = this->index.size();
1038 BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
1039 const size_type bucket_extra_capacity = this->index.capacity()- index_size;
1040 const size_type node_extra_capacity = this->internal_data.pool_size;
1041 const size_type extra_capacity = (bucket_extra_capacity < node_extra_capacity)
1042 ? bucket_extra_capacity : node_extra_capacity;
1043 const size_type index_offset =
1044 (ExtraPointers + extra_capacity) & (size_type(0u) - size_type(index_size != 0));
1045 return index_size - index_offset;
1046 }
1047
1048 //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
1049 //! effect. Otherwise, it is a request for allocation of additional memory.
1050 //! If the request is successful, then capacity() is greater than or equal to
1051 //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
1052 //!
1053 //! <b>Throws</b>: If memory allocation allocation throws.
1054 void reserve(size_type n)
1055 {
1056 STABLE_VECTOR_CHECK_INVARIANT;
1057 if(n > this->max_size()){
1058 throw_length_error("stable_vector::reserve max_size() exceeded");
1059 }
1060
1061 size_type sz = this->size();
1062 size_type old_capacity = this->capacity();
1063 if(n > old_capacity){
1064 index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, n);
1065 const void * old_ptr = &index[0];
1066 this->index.reserve(n + ExtraPointers);
1067 bool realloced = &index[0] != old_ptr;
1068 //Fix the pointers for the newly allocated buffer
1069 if(realloced){
1070 index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
1071 }
1072 //Now fill pool if data is not enough
1073 if((n - sz) > this->internal_data.pool_size){
1074 this->priv_increase_pool((n - sz) - this->internal_data.pool_size);
1075 }
1076 }
1077 }
1078
1079 //! <b>Effects</b>: Tries to deallocate the excess of memory created
1080 //! with previous allocations. The size of the stable_vector is unchanged
1081 //!
1082 //! <b>Throws</b>: If memory allocation throws.
1083 //!
1084 //! <b>Complexity</b>: Linear to size().
1085 void shrink_to_fit()
1086 {
1087 if(this->capacity()){
1088 //First empty allocated node pool
1089 this->priv_clear_pool();
1090 //If empty completely destroy the index, let's recover default-constructed state
1091 if(this->empty()){
1092 this->index.clear();
1093 this->index.shrink_to_fit();
1094 this->internal_data.end_node.up = node_base_ptr_ptr();
1095 }
1096 //Otherwise, try to shrink-to-fit the index and readjust pointers if necessary
1097 else{
1098 const void* old_ptr = &index[0];
1099 this->index.shrink_to_fit();
1100 bool realloced = &index[0] != old_ptr;
1101 //Fix the pointers for the newly allocated buffer
1102 if(realloced){
1103 index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
1104 }
1105 }
1106 }
1107 }
1108
1109 //////////////////////////////////////////////
1110 //
1111 // element access
1112 //
1113 //////////////////////////////////////////////
1114
1115 //! <b>Requires</b>: !empty()
1116 //!
1117 //! <b>Effects</b>: Returns a reference to the first
1118 //! element of the container.
1119 //!
1120 //! <b>Throws</b>: Nothing.
1121 //!
1122 //! <b>Complexity</b>: Constant.
1123 reference front() BOOST_CONTAINER_NOEXCEPT
1124 { return static_cast<node_reference>(*this->index.front()).value; }
1125
1126 //! <b>Requires</b>: !empty()
1127 //!
1128 //! <b>Effects</b>: Returns a const reference to the first
1129 //! element of the container.
1130 //!
1131 //! <b>Throws</b>: Nothing.
1132 //!
1133 //! <b>Complexity</b>: Constant.
1134 const_reference front() const BOOST_CONTAINER_NOEXCEPT
1135 { return static_cast<const_node_reference>(*this->index.front()).value; }
1136
1137 //! <b>Requires</b>: !empty()
1138 //!
1139 //! <b>Effects</b>: Returns a reference to the last
1140 //! element of the container.
1141 //!
1142 //! <b>Throws</b>: Nothing.
1143 //!
1144 //! <b>Complexity</b>: Constant.
1145 reference back() BOOST_CONTAINER_NOEXCEPT
1146 { return static_cast<node_reference>(*this->index[this->size()-1u]).value; }
1147
1148 //! <b>Requires</b>: !empty()
1149 //!
1150 //! <b>Effects</b>: Returns a const reference to the last
1151 //! element of the container.
1152 //!
1153 //! <b>Throws</b>: Nothing.
1154 //!
1155 //! <b>Complexity</b>: Constant.
1156 const_reference back() const BOOST_CONTAINER_NOEXCEPT
1157 { return static_cast<const_node_reference>(*this->index[this->size()-1u]).value; }
1158
1159 //! <b>Requires</b>: size() > n.
1160 //!
1161 //! <b>Effects</b>: Returns a reference to the nth element
1162 //! from the beginning of the container.
1163 //!
1164 //! <b>Throws</b>: Nothing.
1165 //!
1166 //! <b>Complexity</b>: Constant.
1167 reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
1168 {
1169 BOOST_ASSERT(n < this->size());
1170 return static_cast<node_reference>(*this->index[n]).value;
1171 }
1172
1173 //! <b>Requires</b>: size() > n.
1174 //!
1175 //! <b>Effects</b>: Returns a const reference to the nth element
1176 //! from the beginning of the container.
1177 //!
1178 //! <b>Throws</b>: Nothing.
1179 //!
1180 //! <b>Complexity</b>: Constant.
1181 const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
1182 {
1183 BOOST_ASSERT(n < this->size());
1184 return static_cast<const_node_reference>(*this->index[n]).value;
1185 }
1186
1187 //! <b>Requires</b>: size() > n.
1188 //!
1189 //! <b>Effects</b>: Returns a reference to the nth element
1190 //! from the beginning of the container.
1191 //!
1192 //! <b>Throws</b>: std::range_error if n >= size()
1193 //!
1194 //! <b>Complexity</b>: Constant.
1195 reference at(size_type n)
1196 {
1197 if(n >= this->size()){
1198 throw_out_of_range("vector::at invalid subscript");
1199 }
1200 return operator[](n);
1201 }
1202
1203 //! <b>Requires</b>: size() > n.
1204 //!
1205 //! <b>Effects</b>: Returns a const reference to the nth element
1206 //! from the beginning of the container.
1207 //!
1208 //! <b>Throws</b>: std::range_error if n >= size()
1209 //!
1210 //! <b>Complexity</b>: Constant.
1211 const_reference at(size_type n)const
1212 {
1213 if(n >= this->size()){
1214 throw_out_of_range("vector::at invalid subscript");
1215 }
1216 return operator[](n);
1217 }
1218
1219 //////////////////////////////////////////////
1220 //
1221 // modifiers
1222 //
1223 //////////////////////////////////////////////
1224
1225 #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1226
1227 //! <b>Effects</b>: Inserts an object of type T constructed with
1228 //! std::forward<Args>(args)... in the end of the stable_vector.
1229 //!
1230 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
1231 //!
1232 //! <b>Complexity</b>: Amortized constant time.
1233 template<class ...Args>
1234 void emplace_back(Args &&...args)
1235 {
1236 typedef emplace_functor<Args...> EmplaceFunctor;
1237 typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;
1238 EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
1239 this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
1240 }
1241
1242 //! <b>Requires</b>: position must be a valid iterator of *this.
1243 //!
1244 //! <b>Effects</b>: Inserts an object of type T constructed with
1245 //! std::forward<Args>(args)... before position
1246 //!
1247 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
1248 //!
1249 //! <b>Complexity</b>: If position is end(), amortized constant time
1250 //! Linear time otherwise.
1251 template<class ...Args>
1252 iterator emplace(const_iterator position, Args && ...args)
1253 {
1254 //Just call more general insert(pos, size, value) and return iterator
1255 size_type pos_n = position - cbegin();
1256 typedef emplace_functor<Args...> EmplaceFunctor;
1257 typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;
1258 EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
1259 this->insert(position, EmplaceIterator(ef), EmplaceIterator());
1260 return iterator(this->begin() + pos_n);
1261 }
1262
1263 #else
1264
1265 #define BOOST_PP_LOCAL_MACRO(n) \
1266 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
1267 void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
1268 { \
1269 typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
1270 BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >) \
1271 EmplaceFunctor; \
1272 typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator; \
1273 EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \
1274 BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
1275 BOOST_PP_RPAREN_IF(n); \
1276 this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator()); \
1277 } \
1278 \
1279 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
1280 iterator emplace(const_iterator pos \
1281 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
1282 { \
1283 typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
1284 BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >) \
1285 EmplaceFunctor; \
1286 typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator; \
1287 EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \
1288 BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
1289 BOOST_PP_RPAREN_IF(n); \
1290 size_type pos_n = pos - this->cbegin(); \
1291 this->insert(pos, EmplaceIterator(ef), EmplaceIterator()); \
1292 return iterator(this->begin() + pos_n); \
1293 } \
1294 //!
1295 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
1296 #include BOOST_PP_LOCAL_ITERATE()
1297
1298 #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
1299
1300 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1301 //! <b>Effects</b>: Inserts a copy of x at the end of the stable_vector.
1302 //!
1303 //! <b>Throws</b>: If memory allocation throws or
1304 //! T's copy constructor throws.
1305 //!
1306 //! <b>Complexity</b>: Amortized constant time.
1307 void push_back(const T &x);
1308
1309 //! <b>Effects</b>: Constructs a new element in the end of the stable_vector
1310 //! and moves the resources of mx to this new element.
1311 //!
1312 //! <b>Throws</b>: If memory allocation throws.
1313 //!
1314 //! <b>Complexity</b>: Amortized constant time.
1315 void push_back(T &&x);
1316 #else
1317 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
1318 #endif
1319
1320 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1321 //! <b>Requires</b>: position must be a valid iterator of *this.
1322 //!
1323 //! <b>Effects</b>: Insert a copy of x before position.
1324 //!
1325 //! <b>Returns</b>: An iterator to the inserted element.
1326 //!
1327 //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
1328 //!
1329 //! <b>Complexity</b>: If position is end(), amortized constant time
1330 //! Linear time otherwise.
1331 iterator insert(const_iterator position, const T &x);
1332
1333 //! <b>Requires</b>: position must be a valid iterator of *this.
1334 //!
1335 //! <b>Effects</b>: Insert a new element before position with mx's resources.
1336 //!
1337 //! <b>Returns</b>: an iterator to the inserted element.
1338 //!
1339 //! <b>Throws</b>: If memory allocation throws.
1340 //!
1341 //! <b>Complexity</b>: If position is end(), amortized constant time
1342 //! Linear time otherwise.
1343 iterator insert(const_iterator position, T &&x);
1344 #else
1345 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
1346 #endif
1347
1348 //! <b>Requires</b>: pos must be a valid iterator of *this.
1349 //!
1350 //! <b>Effects</b>: Insert n copies of x before position.
1351 //!
1352 //! <b>Returns</b>: an iterator to the first inserted element or position if n is 0.
1353 //!
1354 //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
1355 //!
1356 //! <b>Complexity</b>: Linear to n.
1357 iterator insert(const_iterator position, size_type n, const T& t)
1358 {
1359 STABLE_VECTOR_CHECK_INVARIANT;
1360 typedef constant_iterator<value_type, difference_type> cvalue_iterator;
1361 return this->insert(position, cvalue_iterator(t, n), cvalue_iterator());
1362 }
1363
1364 //! <b>Requires</b>: pos must be a valid iterator of *this.
1365 //!
1366 //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
1367 //!
1368 //! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
1369 //!
1370 //! <b>Throws</b>: If memory allocation throws, T's constructor from a
1371 //! dereferenced InpIt throws or T's copy constructor throws.
1372 //!
1373 //! <b>Complexity</b>: Linear to std::distance [first, last).
1374 template <class InputIterator>
1375 iterator insert(const_iterator position, InputIterator first, InputIterator last
1376 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1377 , typename container_detail::enable_if_c
1378 < !container_detail::is_convertible<InputIterator, size_type>::value
1379 && container_detail::is_input_iterator<InputIterator>::value
1380 >::type * = 0
1381 #endif
1382 )
1383 {
1384 STABLE_VECTOR_CHECK_INVARIANT;
1385 const size_type pos_n = position - this->cbegin();
1386 for(; first != last; ++first){
1387 this->emplace(position, *first);
1388 }
1389 return this->begin() + pos_n;
1390 }
1391
1392 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1393 template <class FwdIt>
1394 iterator insert(const_iterator position, FwdIt first, FwdIt last
1395 , typename container_detail::enable_if_c
1396 < !container_detail::is_convertible<FwdIt, size_type>::value
1397 && !container_detail::is_input_iterator<FwdIt>::value
1398 >::type * = 0
1399 )
1400 {
1401 const size_type num_new = static_cast<size_type>(std::distance(first, last));
1402 const size_type pos = static_cast<size_type>(position - this->cbegin());
1403 if(num_new){
1404 //Fills the node pool and inserts num_new null pointers in pos.
1405 //If a new buffer was needed fixes up pointers up to pos so
1406 //past-new nodes are not aligned until the end of this function
1407 //or in a rollback in case of exception
1408 index_iterator it_past_newly_constructed(this->priv_insert_forward_non_templated(pos, num_new));
1409 const index_iterator it_past_new(it_past_newly_constructed + num_new);
1410 {
1411 //Prepare rollback
1412 insert_rollback rollback(*this, it_past_newly_constructed, it_past_new);
1413 while(first != last){
1414 const node_ptr p = this->priv_get_from_pool();
1415 BOOST_ASSERT(!!p);
1416 //Put it in the index so rollback can return it in pool if construct_in_place throws
1417 *it_past_newly_constructed = p;
1418 //Constructs and fixes up pointers This can throw
1419 this->priv_build_node_from_it(p, it_past_newly_constructed, first);
1420 ++first;
1421 ++it_past_newly_constructed;
1422 }
1423 //rollback.~insert_rollback() called in case of exception
1424 }
1425 //Fix up pointers for past-new nodes (new nodes were fixed during construction) and
1426 //nodes before insertion position in priv_insert_forward_non_templated(...)
1427 index_traits_type::fix_up_pointers_from(this->index, it_past_newly_constructed);
1428 }
1429 return this->begin() + pos;
1430 }
1431 #endif
1432
1433 //! <b>Effects</b>: Removes the last element from the stable_vector.
1434 //!
1435 //! <b>Throws</b>: Nothing.
1436 //!
1437 //! <b>Complexity</b>: Constant time.
1438 void pop_back() BOOST_CONTAINER_NOEXCEPT
1439 { this->erase(--this->cend()); }
1440
1441 //! <b>Effects</b>: Erases the element at position pos.
1442 //!
1443 //! <b>Throws</b>: Nothing.
1444 //!
1445 //! <b>Complexity</b>: Linear to the elements between pos and the
1446 //! last element. Constant if pos is the last element.
1447 iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT
1448 {
1449 STABLE_VECTOR_CHECK_INVARIANT;
1450 const size_type d = position - this->cbegin();
1451 index_iterator it = this->index.begin() + d;
1452 this->priv_delete_node(position.node_pointer());
1453 it = this->index.erase(it);
1454 index_traits_type::fix_up_pointers_from(this->index, it);
1455 return iterator(node_ptr_traits::static_cast_from(*it));
1456 }
1457
1458 //! <b>Effects</b>: Erases the elements pointed by [first, last).
1459 //!
1460 //! <b>Throws</b>: Nothing.
1461 //!
1462 //! <b>Complexity</b>: Linear to the distance between first and last
1463 //! plus linear to the elements between pos and the last element.
1464 iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
1465 {
1466 STABLE_VECTOR_CHECK_INVARIANT;
1467 const const_iterator cbeg(this->cbegin());
1468 const size_type d1 = static_cast<size_type>(first - cbeg),
1469 d2 = static_cast<size_type>(last - cbeg);
1470 size_type d_dif = d2 - d1;
1471 if(d_dif){
1472 multiallocation_chain holder;
1473 const index_iterator it1(this->index.begin() + d1);
1474 const index_iterator it2(it1 + d_dif);
1475 index_iterator it(it1);
1476 while(d_dif--){
1477 node_base_ptr &nb = *it;
1478 ++it;
1479 node_type &n = *node_ptr_traits::static_cast_from(nb);
1480 this->priv_destroy_node(n);
1481 holder.push_back(node_ptr_traits::pointer_to(n));
1482 }
1483 this->priv_put_in_pool(holder);
1484 const index_iterator e = this->index.erase(it1, it2);
1485 index_traits_type::fix_up_pointers_from(this->index, e);
1486 }
1487 return iterator(last.node_pointer());
1488 }
1489
1490 //! <b>Effects</b>: Swaps the contents of *this and x.
1491 //!
1492 //! <b>Throws</b>: Nothing.
1493 //!
1494 //! <b>Complexity</b>: Constant.
1495 void swap(stable_vector & x)
1496 {
1497 STABLE_VECTOR_CHECK_INVARIANT;
1498 container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
1499 container_detail::swap_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
1500 //vector's allocator is swapped here
1501 this->index.swap(x.index);
1502 this->priv_swap_members(x);
1503 }
1504
1505 //! <b>Effects</b>: Erases all the elements of the stable_vector.
1506 //!
1507 //! <b>Throws</b>: Nothing.
1508 //!
1509 //! <b>Complexity</b>: Linear to the number of elements in the stable_vector.
1510 void clear() BOOST_CONTAINER_NOEXCEPT
1511 { this->erase(this->cbegin(),this->cend()); }
1512
1513 /// @cond
1514
1515 private:
1516
1517 class insert_rollback
1518 {
1519 public:
1520
1521 insert_rollback(stable_vector &sv, index_iterator &it_past_constructed, const index_iterator &it_past_new)
1522 : m_sv(sv), m_it_past_constructed(it_past_constructed), m_it_past_new(it_past_new)
1523 {}
1524
1525 ~insert_rollback()
1526 {
1527 if(m_it_past_constructed != m_it_past_new){
1528 m_sv.priv_put_in_pool(node_ptr_traits::static_cast_from(*m_it_past_constructed));
1529 index_iterator e = m_sv.index.erase(m_it_past_constructed, m_it_past_new);
1530 index_traits_type::fix_up_pointers_from(m_sv.index, e);
1531 }
1532 }
1533
1534 private:
1535 stable_vector &m_sv;
1536 index_iterator &m_it_past_constructed;
1537 const index_iterator &m_it_past_new;
1538 };
1539
1540 class push_back_rollback
1541 {
1542 public:
1543 push_back_rollback(stable_vector &sv, const node_ptr &p)
1544 : m_sv(sv), m_p(p)
1545 {}
1546
1547 ~push_back_rollback()
1548 {
1549 if(m_p){
1550 m_sv.priv_put_in_pool(m_p);
1551 }
1552 }
1553
1554 void release()
1555 { m_p = node_ptr(); }
1556
1557 private:
1558 stable_vector &m_sv;
1559 node_ptr m_p;
1560 };
1561
1562 index_iterator priv_insert_forward_non_templated(size_type pos, size_type num_new)
1563 {
1564 index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, num_new);
1565
1566 //Now try to fill the pool with new data
1567 if(this->internal_data.pool_size < num_new){
1568 this->priv_increase_pool(num_new - this->internal_data.pool_size);
1569 }
1570
1571 //Now try to make room in the vector
1572 const node_base_ptr_ptr old_buffer = this->index.data();
1573 this->index.insert(this->index.begin() + pos, num_new, node_ptr());
1574 bool new_buffer = this->index.data() != old_buffer;
1575
1576 //Fix the pointers for the newly allocated buffer
1577 const index_iterator index_beg = this->index.begin();
1578 if(new_buffer){
1579 index_traits_type::fix_up_pointers(index_beg, index_beg + pos);
1580 }
1581 return index_beg + pos;
1582 }
1583
1584 bool priv_capacity_bigger_than_size() const
1585 {
1586 return this->index.capacity() > this->index.size() &&
1587 this->internal_data.pool_size > 0;
1588 }
1589
1590 template <class U>
1591 void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
1592 {
1593 if(this->priv_capacity_bigger_than_size()){
1594 //Enough memory in the pool and in the index
1595 const node_ptr p = this->priv_get_from_pool();
1596 BOOST_ASSERT(!!p);
1597 {
1598 push_back_rollback rollback(*this, p);
1599 //This might throw
1600 this->priv_build_node_from_convertible(p, ::boost::forward<U>(x));
1601 rollback.release();
1602 }
1603 //This can't throw as there is room for a new elements in the index
1604 index_iterator new_index = this->index.insert(this->index.end() - ExtraPointers, p);
1605 index_traits_type::fix_up_pointers_from(this->index, new_index);
1606 }
1607 else{
1608 this->insert(this->cend(), ::boost::forward<U>(x));
1609 }
1610 }
1611
1612 iterator priv_insert(const_iterator position, const value_type &t)
1613 {
1614 typedef constant_iterator<value_type, difference_type> cvalue_iterator;
1615 return this->insert(position, cvalue_iterator(t, 1), cvalue_iterator());
1616 }
1617
1618 iterator priv_insert(const_iterator position, BOOST_RV_REF(T) x)
1619 {
1620 typedef repeat_iterator<T, difference_type> repeat_it;
1621 typedef boost::move_iterator<repeat_it> repeat_move_it;
1622 //Just call more general insert(pos, size, value) and return iterator
1623 return this->insert(position, repeat_move_it(repeat_it(x, 1)), repeat_move_it(repeat_it()));
1624 }
1625
1626 void priv_clear_pool()
1627 {
1628 if(!this->index.empty() && this->index.back()){
1629 node_base_ptr &pool_first_ref = *(this->index.end() - 2);
1630 node_base_ptr &pool_last_ref = this->index.back();
1631
1632 multiallocation_chain holder;
1633 holder.incorporate_after( holder.before_begin()
1634 , node_ptr_traits::static_cast_from(pool_first_ref)
1635 , node_ptr_traits::static_cast_from(pool_last_ref)
1636 , internal_data.pool_size);
1637 this->deallocate_individual(holder);
1638 pool_first_ref = pool_last_ref = 0;
1639 this->internal_data.pool_size = 0;
1640 }
1641 }
1642
1643 void priv_increase_pool(size_type n)
1644 {
1645 node_base_ptr &pool_first_ref = *(this->index.end() - 2);
1646 node_base_ptr &pool_last_ref = this->index.back();
1647 multiallocation_chain holder;
1648 holder.incorporate_after( holder.before_begin()
1649 , node_ptr_traits::static_cast_from(pool_first_ref)
1650 , node_ptr_traits::static_cast_from(pool_last_ref)
1651 , internal_data.pool_size);
1652 multiallocation_chain m;
1653 this->allocate_individual(n, m);
1654 holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
1655 this->internal_data.pool_size += n;
1656 std::pair<node_ptr, node_ptr> data(holder.extract_data());
1657 pool_first_ref = data.first;
1658 pool_last_ref = data.second;
1659 }
1660
1661 void priv_put_in_pool(const node_ptr &p)
1662 {
1663 node_base_ptr &pool_first_ref = *(this->index.end()-2);
1664 node_base_ptr &pool_last_ref = this->index.back();
1665 multiallocation_chain holder;
1666 holder.incorporate_after( holder.before_begin()
1667 , node_ptr_traits::static_cast_from(pool_first_ref)
1668 , node_ptr_traits::static_cast_from(pool_last_ref)
1669 , internal_data.pool_size);
1670 holder.push_front(p);
1671 ++this->internal_data.pool_size;
1672 std::pair<node_ptr, node_ptr> ret(holder.extract_data());
1673 pool_first_ref = ret.first;
1674 pool_last_ref = ret.second;
1675 }
1676
1677 void priv_put_in_pool(multiallocation_chain &ch)
1678 {
1679 node_base_ptr &pool_first_ref = *(this->index.end()-(ExtraPointers-1));
1680 node_base_ptr &pool_last_ref = this->index.back();
1681 ch.incorporate_after( ch.before_begin()
1682 , node_ptr_traits::static_cast_from(pool_first_ref)
1683 , node_ptr_traits::static_cast_from(pool_last_ref)
1684 , internal_data.pool_size);
1685 this->internal_data.pool_size = ch.size();
1686 const std::pair<node_ptr, node_ptr> ret(ch.extract_data());
1687 pool_first_ref = ret.first;
1688 pool_last_ref = ret.second;
1689 }
1690
1691 node_ptr priv_get_from_pool()
1692 {
1693 //Precondition: index is not empty
1694 BOOST_ASSERT(!this->index.empty());
1695 node_base_ptr &pool_first_ref = *(this->index.end() - (ExtraPointers-1));
1696 node_base_ptr &pool_last_ref = this->index.back();
1697 multiallocation_chain holder;
1698 holder.incorporate_after( holder.before_begin()
1699 , node_ptr_traits::static_cast_from(pool_first_ref)
1700 , node_ptr_traits::static_cast_from(pool_last_ref)
1701 , internal_data.pool_size);
1702 node_ptr ret = holder.pop_front();
1703 --this->internal_data.pool_size;
1704 if(!internal_data.pool_size){
1705 pool_first_ref = pool_last_ref = node_ptr();
1706 }
1707 else{
1708 const std::pair<node_ptr, node_ptr> data(holder.extract_data());
1709 pool_first_ref = data.first;
1710 pool_last_ref = data.second;
1711 }
1712 return ret;
1713 }
1714
1715 node_ptr priv_get_end_node() const
1716 {
1717 return node_ptr_traits::pointer_to
1718 (static_cast<node_type&>(const_cast<node_base_type&>(this->internal_data.end_node)));
1719 }
1720
1721 void priv_destroy_node(const node_type &n)
1722 {
1723 allocator_traits<node_allocator_type>::
1724 destroy(this->priv_node_alloc(), container_detail::addressof(n.value));
1725 static_cast<const node_base_type*>(&n)->~node_base_type();
1726 }
1727
1728 void priv_delete_node(const node_ptr &n)
1729 {
1730 this->priv_destroy_node(*n);
1731 this->priv_put_in_pool(n);
1732 }
1733
1734 template<class Iterator>
1735 void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it)
1736 {
1737 //This can throw
1738 boost::container::construct_in_place
1739 ( this->priv_node_alloc()
1740 , container_detail::addressof(p->value)
1741 , it);
1742 //This does not throw
1743 ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p)))
1744 node_base_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
1745 }
1746
1747 template<class ValueConvertible>
1748 void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible)
1749 {
1750 //This can throw
1751 boost::container::allocator_traits<node_allocator_type>::construct
1752 ( this->priv_node_alloc()
1753 , container_detail::addressof(p->value)
1754 , ::boost::forward<ValueConvertible>(value_convertible));
1755 //This does not throw
1756 ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p))) node_base_type;
1757 }
1758
1759 void priv_swap_members(stable_vector &x)
1760 {
1761 boost::container::swap_dispatch(this->internal_data.pool_size, x.internal_data.pool_size);
1762 index_traits_type::readjust_end_node(this->index, this->internal_data.end_node);
1763 index_traits_type::readjust_end_node(x.index, x.internal_data.end_node);
1764 }
1765
1766 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
1767 bool priv_invariant()const
1768 {
1769 index_type & index_ref = const_cast<index_type&>(this->index);
1770
1771 if(index.empty())
1772 return !this->capacity() && !this->size();
1773 if(this->priv_get_end_node() != *(index.end() - ExtraPointers)){
1774 return false;
1775 }
1776
1777 if(!index_traits_type::invariants(index_ref)){
1778 return false;
1779 }
1780
1781 size_type n = this->capacity() - this->size();
1782 node_base_ptr &pool_first_ref = *(index_ref.end() - (ExtraPointers-1));
1783 node_base_ptr &pool_last_ref = index_ref.back();
1784 multiallocation_chain holder;
1785 holder.incorporate_after( holder.before_begin()
1786 , node_ptr_traits::static_cast_from(pool_first_ref)
1787 , node_ptr_traits::static_cast_from(pool_last_ref)
1788 , internal_data.pool_size);
1789 typename multiallocation_chain::iterator beg(holder.begin()), end(holder.end());
1790 size_type num_pool = 0;
1791 while(beg != end){
1792 ++num_pool;
1793 ++beg;
1794 }
1795 return n >= num_pool && num_pool == internal_data.pool_size;
1796 }
1797
1798 class invariant_checker
1799 {
1800 invariant_checker(const invariant_checker &);
1801 invariant_checker & operator=(const invariant_checker &);
1802 const stable_vector* p;
1803
1804 public:
1805 invariant_checker(const stable_vector& v):p(&v){}
1806 ~invariant_checker(){BOOST_ASSERT(p->priv_invariant());}
1807 void touch(){}
1808 };
1809 #endif
1810
1811 class ebo_holder
1812 : public node_allocator_type
1813 {
1814 private:
1815 BOOST_MOVABLE_BUT_NOT_COPYABLE(ebo_holder)
1816
1817 public:
1818 template<class AllocatorRLValue>
1819 explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
1820 : node_allocator_type(boost::forward<AllocatorRLValue>(a))
1821 , pool_size(0)
1822 , end_node()
1823 {}
1824
1825 ebo_holder()
1826 : node_allocator_type()
1827 , pool_size(0)
1828 , end_node()
1829 {}
1830
1831 size_type pool_size;
1832 node_base_type end_node;
1833 } internal_data;
1834
1835 node_allocator_type &priv_node_alloc() { return internal_data; }
1836 const node_allocator_type &priv_node_alloc() const { return internal_data; }
1837
1838 index_type index;
1839 /// @endcond
1840 };
1841
1842 template <typename T,typename Allocator>
1843 bool operator==(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1844 {
1845 return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
1846 }
1847
1848 template <typename T,typename Allocator>
1849 bool operator< (const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1850 {
1851 return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
1852 }
1853
1854 template <typename T,typename Allocator>
1855 bool operator!=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1856 {
1857 return !(x==y);
1858 }
1859
1860 template <typename T,typename Allocator>
1861 bool operator> (const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1862 {
1863 return y<x;
1864 }
1865
1866 template <typename T,typename Allocator>
1867 bool operator>=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1868 {
1869 return !(x<y);
1870 }
1871
1872 template <typename T,typename Allocator>
1873 bool operator<=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
1874 {
1875 return !(x>y);
1876 }
1877
1878 // specialized algorithms:
1879
1880 template <typename T, typename Allocator>
1881 void swap(stable_vector<T,Allocator>& x,stable_vector<T,Allocator>& y)
1882 {
1883 x.swap(y);
1884 }
1885
1886 /// @cond
1887
1888 #undef STABLE_VECTOR_CHECK_INVARIANT
1889
1890 /// @endcond
1891
1892 /*
1893
1894 //!has_trivial_destructor_after_move<> == true_type
1895 //!specialization for optimizations
1896 template <class T, class Allocator>
1897 struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> >
1898 : public has_trivial_destructor_after_move<Allocator>::value
1899 {};
1900
1901 */
1902
1903 }}
1904
1905 #include <boost/container/detail/config_end.hpp>
1906
1907 #endif //BOOST_CONTAINER_STABLE_VECTOR_HPP