Mercurial > hg > vamp-build-and-test
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 |