File indexing completed on 2025-01-18 09:30:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef BOOST_CONTAINER_STABLE_VECTOR_HPP
0020 #define BOOST_CONTAINER_STABLE_VECTOR_HPP
0021
0022 #ifndef BOOST_CONFIG_HPP
0023 # include <boost/config.hpp>
0024 #endif
0025
0026 #if defined(BOOST_HAS_PRAGMA_ONCE)
0027 # pragma once
0028 #endif
0029
0030 #include <boost/container/detail/config_begin.hpp>
0031 #include <boost/container/detail/workaround.hpp>
0032
0033
0034 #include <boost/container/allocator_traits.hpp>
0035 #include <boost/container/container_fwd.hpp>
0036 #include <boost/container/new_allocator.hpp> //new_allocator
0037 #include <boost/container/throw_exception.hpp>
0038
0039 #include <boost/container/detail/addressof.hpp>
0040 #include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
0041 #include <boost/container/detail/alloc_helpers.hpp>
0042 #include <boost/container/detail/allocator_version_traits.hpp>
0043 #include <boost/container/detail/construct_in_place.hpp>
0044 #include <boost/container/detail/iterator.hpp>
0045 #include <boost/container/detail/iterators.hpp>
0046 #include <boost/container/detail/placement_new.hpp>
0047 #include <boost/move/detail/to_raw_pointer.hpp>
0048 #include <boost/container/detail/type_traits.hpp>
0049
0050 #include <boost/intrusive/pointer_traits.hpp>
0051
0052 #include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
0053
0054 #include <boost/move/utility_core.hpp>
0055 #include <boost/move/iterator.hpp>
0056 #include <boost/move/adl_move_swap.hpp>
0057 #include <boost/move/detail/force_ptr.hpp>
0058
0059 #include <boost/move/detail/move_helpers.hpp>
0060 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
0061
0062 #include <boost/assert.hpp>
0063
0064 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0065 #include <initializer_list>
0066 #endif
0067
0068 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0069 #include <boost/container/vector.hpp>
0070
0071 #endif
0072
0073 namespace boost {
0074 namespace container {
0075
0076 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0077
0078 namespace stable_vector_detail{
0079
0080 template <class C>
0081 class clear_on_destroy
0082 {
0083 public:
0084 BOOST_CONTAINER_FORCEINLINE clear_on_destroy(C &c)
0085 : c_(c), do_clear_(true)
0086 {}
0087
0088 BOOST_CONTAINER_FORCEINLINE void release()
0089 { do_clear_ = false; }
0090
0091 BOOST_CONTAINER_FORCEINLINE ~clear_on_destroy()
0092 {
0093 if(do_clear_){
0094 c_.clear();
0095 c_.priv_clear_pool();
0096 }
0097 }
0098
0099 private:
0100 clear_on_destroy(const clear_on_destroy &);
0101 clear_on_destroy &operator=(const clear_on_destroy &);
0102 C &c_;
0103 bool do_clear_;
0104 };
0105
0106 template<typename Pointer>
0107 struct node;
0108
0109 template<class VoidPtr>
0110 struct node_base
0111 {
0112 private:
0113 typedef typename boost::intrusive::
0114 pointer_traits<VoidPtr> void_ptr_traits;
0115 typedef typename void_ptr_traits::
0116 template rebind_pointer
0117 <node_base>::type node_base_ptr;
0118
0119 public:
0120 typedef typename void_ptr_traits::
0121 template rebind_pointer
0122 <node_base_ptr>::type node_base_ptr_ptr;
0123
0124 public:
0125 BOOST_CONTAINER_FORCEINLINE explicit node_base(const node_base_ptr_ptr &n)
0126 : up(n)
0127 {}
0128
0129 BOOST_CONTAINER_FORCEINLINE node_base()
0130 : up()
0131 {}
0132
0133 node_base_ptr_ptr up;
0134 };
0135
0136
0137 template<typename Pointer>
0138 struct node
0139 : public node_base
0140 <typename ::boost::intrusive::pointer_traits<Pointer>::template
0141 rebind_pointer<void>::type
0142 >
0143 {
0144 public:
0145 typedef typename ::boost::intrusive::pointer_traits<Pointer>::element_type T;
0146 typedef node_base
0147 <typename ::boost::intrusive::pointer_traits<Pointer>::template
0148 rebind_pointer<void>::type
0149 > hook_type;
0150
0151 typedef typename boost::container::dtl::aligned_storage
0152 <sizeof(T), boost::container::dtl::alignment_of<T>::value>::type storage_t;
0153 storage_t m_storage;
0154
0155 BOOST_CONTAINER_FORCEINLINE explicit node(const typename hook_type::node_base_ptr_ptr &n)
0156 : hook_type(n)
0157 {}
0158
0159 BOOST_CONTAINER_FORCEINLINE node()
0160 {}
0161
0162 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000)
0163 #pragma GCC diagnostic push
0164 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
0165 #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING
0166 # endif
0167
0168 BOOST_CONTAINER_FORCEINLINE T &get_data()
0169 { return *boost::move_detail::force_ptr<T*>(this->m_storage.data); }
0170
0171 BOOST_CONTAINER_FORCEINLINE const T &get_data() const
0172 { return *boost::move_detail::force_ptr<const T*>(this->m_storage.data); }
0173
0174 BOOST_CONTAINER_FORCEINLINE T *get_data_ptr()
0175 { return boost::move_detail::force_ptr<T*>(this->m_storage.data); }
0176
0177 BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const
0178 { return boost::move_detail::force_ptr<const T*>(this->m_storage.data); }
0179
0180 BOOST_CONTAINER_FORCEINLINE ~node()
0181 { boost::move_detail::force_ptr<T*>(this->m_storage.data)->~T(); }
0182
0183 #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING)
0184 #pragma GCC diagnostic pop
0185 #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING
0186 # endif
0187
0188 BOOST_CONTAINER_FORCEINLINE void destroy_header()
0189 { static_cast<hook_type*>(this)->~hook_type(); }
0190 };
0191
0192 template<class VoidPtr, class VoidAllocator>
0193 struct index_traits
0194 {
0195 typedef boost::intrusive::
0196 pointer_traits
0197 <VoidPtr> void_ptr_traits;
0198 typedef stable_vector_detail::
0199 node_base<VoidPtr> node_base_type;
0200 typedef typename void_ptr_traits::template
0201 rebind_pointer<node_base_type>::type node_base_ptr;
0202 typedef typename void_ptr_traits::template
0203 rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
0204 typedef boost::intrusive::
0205 pointer_traits<node_base_ptr> node_base_ptr_traits;
0206 typedef boost::intrusive::
0207 pointer_traits<node_base_ptr_ptr> node_base_ptr_ptr_traits;
0208 typedef typename allocator_traits<VoidAllocator>::
0209 template portable_rebind_alloc
0210 <node_base_ptr>::type node_base_ptr_allocator;
0211 typedef ::boost::container::vector
0212 <node_base_ptr, node_base_ptr_allocator> index_type;
0213 typedef typename index_type::iterator index_iterator;
0214 typedef typename index_type::const_iterator const_index_iterator;
0215 typedef typename index_type::size_type size_type;
0216
0217 static const size_type ExtraPointers = 3;
0218
0219
0220
0221
0222
0223
0224 BOOST_CONTAINER_FORCEINLINE static node_base_ptr_ptr ptr_to_node_base_ptr(node_base_ptr &n)
0225 { return node_base_ptr_ptr_traits::pointer_to(n); }
0226
0227 static void fix_up_pointers(index_iterator first, index_iterator last)
0228 {
0229 while(first != last){
0230 typedef typename index_type::reference node_base_ptr_ref;
0231 node_base_ptr_ref nbp = *first;
0232 nbp->up = index_traits::ptr_to_node_base_ptr(nbp);
0233 ++first;
0234 }
0235 }
0236
0237 BOOST_CONTAINER_FORCEINLINE static index_iterator get_fix_up_end(index_type &index)
0238 { return index.end() - (ExtraPointers - 1); }
0239
0240 BOOST_CONTAINER_FORCEINLINE static void fix_up_pointers_from(index_type & index, index_iterator first)
0241 { index_traits::fix_up_pointers(first, index_traits::get_fix_up_end(index)); }
0242
0243 static void readjust_end_node(index_type &index, node_base_type &end_node)
0244 {
0245 if(!index.empty()){
0246 index_iterator end_node_it(index_traits::get_fix_up_end(index));
0247 node_base_ptr &end_node_idx_ref = *(--end_node_it);
0248 end_node_idx_ref = node_base_ptr_traits::pointer_to(end_node);
0249 end_node.up = node_base_ptr_ptr_traits::pointer_to(end_node_idx_ref);
0250 }
0251 else{
0252 end_node.up = node_base_ptr_ptr();
0253 }
0254 }
0255
0256 static void initialize_end_node(index_type &index, node_base_type &end_node, const size_type index_capacity_if_empty)
0257 {
0258 if(index.empty()){
0259 index.reserve(index_capacity_if_empty + ExtraPointers);
0260 index.resize(ExtraPointers);
0261 node_base_ptr &end_node_ref = *index.data();
0262 end_node_ref = node_base_ptr_traits::pointer_to(end_node);
0263 end_node.up = index_traits::ptr_to_node_base_ptr(end_node_ref);
0264 }
0265 }
0266
0267 #ifdef STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
0268 static bool invariants(index_type &index)
0269 {
0270 for( index_iterator it = index.begin()
0271 , it_end = index_traits::get_fix_up_end(index)
0272 ; it != it_end
0273 ; ++it){
0274 if((*it)->up != index_traits::ptr_to_node_base_ptr(*it)){
0275 return false;
0276 }
0277 }
0278 return true;
0279 }
0280 #endif
0281 };
0282
0283 }
0284
0285 template<typename Pointer, bool IsConst>
0286 class stable_vector_iterator
0287 {
0288 typedef boost::intrusive::pointer_traits<Pointer> non_const_ptr_traits;
0289 public:
0290 typedef std::random_access_iterator_tag iterator_category;
0291 typedef typename non_const_ptr_traits::element_type value_type;
0292 typedef typename non_const_ptr_traits::difference_type difference_type;
0293 typedef typename non_const_ptr_traits::size_type size_type;
0294 typedef typename ::boost::container::dtl::if_c
0295 < IsConst
0296 , typename non_const_ptr_traits::template
0297 rebind_pointer<const value_type>::type
0298 , Pointer
0299 >::type pointer;
0300 typedef boost::intrusive::pointer_traits<pointer> ptr_traits;
0301 typedef typename ptr_traits::reference reference;
0302
0303 typedef typename non_const_ptr_traits::template
0304 rebind_pointer<void>::type void_ptr;
0305 typedef stable_vector_detail::node<Pointer> node_type;
0306 typedef stable_vector_detail::node_base<void_ptr> node_base_type;
0307 typedef typename non_const_ptr_traits::template
0308 rebind_pointer<node_type>::type node_ptr;
0309 typedef boost::intrusive::
0310 pointer_traits<node_ptr> node_ptr_traits;
0311 typedef typename non_const_ptr_traits::template
0312 rebind_pointer<node_base_type>::type node_base_ptr;
0313 typedef typename non_const_ptr_traits::template
0314 rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
0315
0316 class nat
0317 {
0318 public:
0319 node_base_ptr node_pointer() const
0320 { return node_base_ptr(); }
0321 };
0322 typedef typename dtl::if_c< IsConst
0323 , stable_vector_iterator<Pointer, false>
0324 , nat>::type nonconst_iterator;
0325
0326 node_base_ptr m_pn;
0327
0328 public:
0329
0330 BOOST_CONTAINER_FORCEINLINE explicit stable_vector_iterator(node_base_ptr p) BOOST_NOEXCEPT_OR_NOTHROW
0331 : m_pn(p)
0332 {}
0333
0334 BOOST_CONTAINER_FORCEINLINE stable_vector_iterator() BOOST_NOEXCEPT_OR_NOTHROW
0335 : m_pn()
0336 {}
0337
0338 BOOST_CONTAINER_FORCEINLINE stable_vector_iterator(const stable_vector_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
0339 : m_pn(other.node_pointer())
0340 {}
0341
0342 BOOST_CONTAINER_FORCEINLINE stable_vector_iterator(const nonconst_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
0343 : m_pn(other.node_pointer())
0344 {}
0345
0346 BOOST_CONTAINER_FORCEINLINE stable_vector_iterator & operator=(const stable_vector_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
0347 { m_pn = other.node_pointer(); return *this; }
0348
0349 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0350 node_ptr node_pointer() const BOOST_NOEXCEPT_OR_NOTHROW
0351 { return node_ptr_traits::static_cast_from(m_pn); }
0352
0353 public:
0354
0355 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0356 reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
0357 { return node_pointer()->get_data(); }
0358
0359 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0360 pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
0361 { return ptr_traits::pointer_to(this->operator*()); }
0362
0363
0364 BOOST_CONTAINER_FORCEINLINE stable_vector_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
0365 {
0366 node_base_ptr_ptr p(this->m_pn->up);
0367 this->m_pn = *(++p);
0368 return *this;
0369 }
0370
0371 BOOST_CONTAINER_FORCEINLINE stable_vector_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
0372 { stable_vector_iterator tmp(*this); ++*this; return stable_vector_iterator(tmp); }
0373
0374 BOOST_CONTAINER_FORCEINLINE stable_vector_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
0375 {
0376 node_base_ptr_ptr p(this->m_pn->up);
0377 this->m_pn = *(--p);
0378 return *this;
0379 }
0380
0381 BOOST_CONTAINER_FORCEINLINE stable_vector_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
0382 { stable_vector_iterator tmp(*this); --*this; return stable_vector_iterator(tmp); }
0383
0384 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0385 reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
0386 { return node_ptr_traits::static_cast_from(this->m_pn->up[off])->get_data(); }
0387
0388
0389 BOOST_CONTAINER_FORCEINLINE stable_vector_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0390 {
0391 if(off) this->m_pn = this->m_pn->up[off];
0392 return *this;
0393 }
0394
0395 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0396 friend stable_vector_iterator operator+(const stable_vector_iterator &left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0397 {
0398 stable_vector_iterator tmp(left);
0399 tmp += off;
0400 return tmp;
0401 }
0402
0403 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0404 friend stable_vector_iterator operator+(difference_type off, const stable_vector_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
0405 {
0406 stable_vector_iterator tmp(right);
0407 tmp += off;
0408 return tmp;
0409 }
0410
0411 BOOST_CONTAINER_FORCEINLINE stable_vector_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0412 { *this += -off; return *this; }
0413
0414 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0415 friend stable_vector_iterator operator-(const stable_vector_iterator &left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0416 {
0417 stable_vector_iterator tmp(left);
0418 tmp -= off;
0419 return tmp;
0420 }
0421
0422
0423 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0424 friend difference_type operator-(const stable_vector_iterator &left, const stable_vector_iterator &right) BOOST_NOEXCEPT_OR_NOTHROW
0425 { return left.m_pn->up - right.m_pn->up; }
0426
0427
0428 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0429 friend bool operator== (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0430 { return l.m_pn == r.m_pn; }
0431
0432 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0433 friend bool operator!= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0434 { return l.m_pn != r.m_pn; }
0435
0436 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0437 friend bool operator< (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0438 { return l.m_pn->up < r.m_pn->up; }
0439
0440 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0441 friend bool operator<= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0442 { return l.m_pn->up <= r.m_pn->up; }
0443
0444 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0445 friend bool operator> (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0446 { return l.m_pn->up > r.m_pn->up; }
0447
0448 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0449 friend bool operator>= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0450 { return l.m_pn->up >= r.m_pn->up; }
0451 };
0452
0453 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
0454
0455 #define BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT \
0456 invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \
0457 BOOST_JOIN(check_invariant_,__LINE__).touch();
0458
0459 #else
0460
0461 #define BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
0462
0463 #endif
0464
0465 #endif
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
0502 template <class T, class Allocator = void >
0503 #else
0504 template <class T, class Allocator>
0505 #endif
0506 class stable_vector
0507 {
0508 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0509 typedef typename real_allocator<T, Allocator>::type ValueAllocator;
0510 typedef allocator_traits<ValueAllocator> allocator_traits_type;
0511 typedef boost::intrusive::
0512 pointer_traits
0513 <typename allocator_traits_type::pointer> ptr_traits;
0514 typedef typename ptr_traits::
0515 template rebind_pointer<void>::type void_ptr;
0516 typedef typename allocator_traits_type::
0517 template portable_rebind_alloc
0518 <void>::type void_allocator_type;
0519 typedef stable_vector_detail::index_traits
0520 <void_ptr, void_allocator_type> index_traits_type;
0521 typedef typename index_traits_type::node_base_type node_base_type;
0522 typedef typename index_traits_type::node_base_ptr node_base_ptr;
0523 typedef typename index_traits_type::
0524 node_base_ptr_ptr node_base_ptr_ptr;
0525 typedef typename index_traits_type::
0526 node_base_ptr_traits node_base_ptr_traits;
0527 typedef typename index_traits_type::
0528 node_base_ptr_ptr_traits node_base_ptr_ptr_traits;
0529 typedef typename index_traits_type::index_type index_type;
0530 typedef typename index_traits_type::index_iterator index_iterator;
0531 typedef typename index_traits_type::
0532 const_index_iterator const_index_iterator;
0533 typedef stable_vector_detail::node
0534 <typename ptr_traits::pointer> node_type;
0535 typedef typename ptr_traits::template
0536 rebind_pointer<node_type>::type node_ptr;
0537 typedef boost::intrusive::
0538 pointer_traits<node_ptr> node_ptr_traits;
0539 typedef typename ptr_traits::template
0540 rebind_pointer<const node_type>::type const_node_ptr;
0541 typedef boost::intrusive::
0542 pointer_traits<const_node_ptr> const_node_ptr_traits;
0543 typedef typename node_ptr_traits::reference node_reference;
0544 typedef typename const_node_ptr_traits::reference const_node_reference;
0545
0546 typedef ::boost::container::dtl::integral_constant
0547 <unsigned, boost::container::dtl::
0548 version<ValueAllocator>::value> alloc_version;
0549 typedef typename allocator_traits_type::
0550 template portable_rebind_alloc
0551 <node_type>::type node_allocator_type;
0552
0553 typedef ::boost::container::dtl::
0554 allocator_version_traits<node_allocator_type> allocator_version_traits_t;
0555 typedef typename allocator_version_traits_t::multiallocation_chain multiallocation_chain;
0556
0557 BOOST_CONTAINER_FORCEINLINE node_ptr allocate_one()
0558 { return allocator_version_traits_t::allocate_one(this->priv_node_alloc()); }
0559
0560 BOOST_CONTAINER_FORCEINLINE void deallocate_one(const node_ptr &p)
0561 { allocator_version_traits_t::deallocate_one(this->priv_node_alloc(), p); }
0562
0563 BOOST_CONTAINER_FORCEINLINE void allocate_individual(typename allocator_traits_type::size_type n, multiallocation_chain &m)
0564 { allocator_version_traits_t::allocate_individual(this->priv_node_alloc(), n, m); }
0565
0566 BOOST_CONTAINER_FORCEINLINE void deallocate_individual(multiallocation_chain &holder)
0567 { allocator_version_traits_t::deallocate_individual(this->priv_node_alloc(), holder); }
0568
0569 friend class stable_vector_detail::clear_on_destroy<stable_vector>;
0570 typedef stable_vector_iterator
0571 < typename allocator_traits<ValueAllocator>::pointer
0572 , false> iterator_impl;
0573 typedef stable_vector_iterator
0574 < typename allocator_traits<ValueAllocator>::pointer
0575 , true> const_iterator_impl;
0576 #endif
0577 public:
0578
0579
0580
0581
0582
0583
0584 typedef T value_type;
0585 typedef typename ::boost::container::allocator_traits<ValueAllocator>::pointer pointer;
0586 typedef typename ::boost::container::allocator_traits<ValueAllocator>::const_pointer const_pointer;
0587 typedef typename ::boost::container::allocator_traits<ValueAllocator>::reference reference;
0588 typedef typename ::boost::container::allocator_traits<ValueAllocator>::const_reference const_reference;
0589 typedef typename ::boost::container::allocator_traits<ValueAllocator>::size_type size_type;
0590 typedef typename ::boost::container::allocator_traits<ValueAllocator>::difference_type difference_type;
0591 typedef ValueAllocator allocator_type;
0592 typedef node_allocator_type stored_allocator_type;
0593 typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
0594 typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
0595 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator;
0596 typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
0597
0598 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0599 private:
0600 BOOST_COPYABLE_AND_MOVABLE(stable_vector)
0601 static const size_type ExtraPointers = index_traits_type::ExtraPointers;
0602
0603 class insert_rollback;
0604 friend class insert_rollback;
0605
0606 class push_back_rollback;
0607 friend class push_back_rollback;
0608 #endif
0609
0610 public:
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622 BOOST_CONTAINER_FORCEINLINE stable_vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<ValueAllocator>::value)
0623 : internal_data(), index()
0624 {
0625 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0626 }
0627
0628
0629
0630
0631
0632
0633 BOOST_CONTAINER_FORCEINLINE explicit stable_vector(const allocator_type& al) BOOST_NOEXCEPT_OR_NOTHROW
0634 : internal_data(al), index(al)
0635 {
0636 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0637 }
0638
0639
0640
0641
0642
0643
0644
0645
0646 explicit stable_vector(size_type n)
0647 : internal_data(), index()
0648 {
0649 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0650 this->resize(n);
0651 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0652 cod.release();
0653 }
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664 stable_vector(size_type n, default_init_t)
0665 : internal_data(), index()
0666 {
0667 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0668 this->resize(n, default_init);
0669 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0670 cod.release();
0671 }
0672
0673
0674
0675
0676
0677
0678
0679
0680 explicit stable_vector(size_type n, const allocator_type &a)
0681 : internal_data(), index(a)
0682 {
0683 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0684 this->resize(n);
0685 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0686 cod.release();
0687 }
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698 stable_vector(size_type n, default_init_t, const allocator_type &a)
0699 : internal_data(), index(a)
0700 {
0701 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0702 this->resize(n, default_init);
0703 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0704 cod.release();
0705 }
0706
0707
0708
0709
0710
0711
0712
0713
0714 stable_vector(size_type n, const T& t, const allocator_type& al = allocator_type())
0715 : internal_data(al), index(al)
0716 {
0717 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0718 this->insert(this->cend(), n, t);
0719 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0720 cod.release();
0721 }
0722
0723
0724
0725
0726
0727
0728
0729
0730 template <class InputIterator>
0731 stable_vector(InputIterator first,InputIterator last, const allocator_type& al = allocator_type())
0732 : internal_data(al), index(al)
0733 {
0734 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0735 this->insert(this->cend(), first, last);
0736 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0737 cod.release();
0738 }
0739
0740
0741
0742
0743
0744
0745 stable_vector(const stable_vector& x)
0746 : internal_data(allocator_traits<node_allocator_type>::
0747 select_on_container_copy_construction(x.priv_node_alloc()))
0748 , index(allocator_traits<allocator_type>::
0749 select_on_container_copy_construction(x.index.get_stored_allocator()))
0750 {
0751 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0752 this->insert(this->cend(), x.begin(), x.end());
0753 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0754 cod.release();
0755 }
0756
0757 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0758
0759
0760
0761
0762
0763
0764
0765 stable_vector(std::initializer_list<value_type> il, const allocator_type& l = allocator_type())
0766 : internal_data(l), index(l)
0767 {
0768 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0769 insert(cend(), il.begin(), il.end());
0770 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0771 cod.release();
0772 }
0773 #endif
0774
0775
0776
0777
0778
0779
0780 BOOST_CONTAINER_FORCEINLINE stable_vector(BOOST_RV_REF(stable_vector) x) BOOST_NOEXCEPT_OR_NOTHROW
0781 : internal_data(boost::move(x.priv_node_alloc())), index(boost::move(x.index))
0782 {
0783 this->priv_swap_members(x);
0784 }
0785
0786
0787
0788
0789
0790
0791 stable_vector(const stable_vector& x, const allocator_type &a)
0792 : internal_data(a), index(a)
0793 {
0794 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0795 this->insert(this->cend(), x.begin(), x.end());
0796 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0797 cod.release();
0798 }
0799
0800
0801
0802
0803
0804
0805
0806 stable_vector(BOOST_RV_REF(stable_vector) x, const allocator_type &a)
0807 : internal_data(a), index(a)
0808 {
0809 if(this->priv_node_alloc() == x.priv_node_alloc()){
0810 this->index.swap(x.index);
0811 this->priv_swap_members(x);
0812 }
0813 else{
0814 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0815 this->insert(this->cend(), boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
0816 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0817 cod.release();
0818 }
0819 }
0820
0821
0822
0823
0824
0825
0826
0827 ~stable_vector()
0828 {
0829 this->clear();
0830 this->priv_clear_pool();
0831 }
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841 stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
0842 {
0843 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0844 if (BOOST_LIKELY(this != &x)) {
0845 node_allocator_type &this_alloc = this->priv_node_alloc();
0846 const node_allocator_type &x_alloc = x.priv_node_alloc();
0847 dtl::bool_<allocator_traits_type::
0848 propagate_on_container_copy_assignment::value> flag;
0849 if(flag && this_alloc != x_alloc){
0850 this->clear();
0851 this->shrink_to_fit();
0852 }
0853 dtl::assign_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
0854 dtl::assign_alloc(this->index.get_stored_allocator(), x.index.get_stored_allocator(), flag);
0855 this->assign(x.begin(), x.end());
0856 }
0857 return *this;
0858 }
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871 stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
0872 BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
0873 || allocator_traits_type::is_always_equal::value)
0874 {
0875
0876 if (BOOST_LIKELY(this != &x)) {
0877 node_allocator_type &this_alloc = this->priv_node_alloc();
0878 node_allocator_type &x_alloc = x.priv_node_alloc();
0879 const bool propagate_alloc = allocator_traits_type::
0880 propagate_on_container_move_assignment::value;
0881 dtl::bool_<propagate_alloc> flag;
0882 const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
0883
0884
0885 if(propagate_alloc || allocators_equal){
0886 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
0887
0888 this->clear();
0889
0890 dtl::move_alloc(this_alloc, x_alloc, flag);
0891
0892 this->index.swap(x.index);
0893 this->priv_swap_members(x);
0894 }
0895
0896 else{
0897 this->assign( boost::make_move_iterator(x.begin())
0898 , boost::make_move_iterator(x.end()));
0899 }
0900 }
0901 return *this;
0902 }
0903
0904 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0905
0906
0907
0908 stable_vector& operator=(std::initializer_list<value_type> il)
0909 {
0910 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0911 assign(il.begin(), il.end());
0912 return *this;
0913 }
0914 #endif
0915
0916
0917
0918
0919
0920
0921 BOOST_CONTAINER_FORCEINLINE void assign(size_type n, const T& t)
0922 {
0923 typedef constant_iterator<value_type> cvalue_iterator;
0924 this->assign(cvalue_iterator(t, n), cvalue_iterator());
0925 }
0926
0927
0928
0929
0930
0931
0932
0933 template<typename InputIterator>
0934 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
0935 typename dtl::disable_if_convertible<InputIterator, size_type>::type
0936 #else
0937 void
0938 #endif
0939 assign(InputIterator first,InputIterator last)
0940 {
0941 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0942 iterator first1 = this->begin();
0943 iterator last1 = this->end();
0944 for ( ; first1 != last1 && first != last; ++first1, ++first)
0945 *first1 = *first;
0946 if (first == last){
0947 this->erase(first1, last1);
0948 }
0949 else{
0950 this->insert(last1, first, last);
0951 }
0952 }
0953
0954 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0955
0956
0957
0958
0959
0960 BOOST_CONTAINER_FORCEINLINE void assign(std::initializer_list<value_type> il)
0961 {
0962 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0963 assign(il.begin(), il.end());
0964 }
0965 #endif
0966
0967
0968
0969
0970
0971
0972 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0973 allocator_type get_allocator() const
0974 { return this->priv_node_alloc(); }
0975
0976
0977
0978
0979
0980
0981
0982
0983 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0984 const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
0985 { return this->priv_node_alloc(); }
0986
0987
0988
0989
0990
0991
0992
0993
0994 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0995 stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
0996 { return this->priv_node_alloc(); }
0997
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1010 iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
1011 { return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); }
1012
1013
1014
1015
1016
1017
1018 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1019 const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
1020 { return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; }
1021
1022
1023
1024
1025
1026
1027 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1028 iterator end() BOOST_NOEXCEPT_OR_NOTHROW
1029 { return iterator(this->priv_get_end_node()); }
1030
1031
1032
1033
1034
1035
1036 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1037 const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
1038 { return const_iterator(this->priv_get_end_node()); }
1039
1040
1041
1042
1043
1044
1045
1046 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1047 reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
1048 { return reverse_iterator(this->end()); }
1049
1050
1051
1052
1053
1054
1055
1056 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1057 const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1058 { return const_reverse_iterator(this->end()); }
1059
1060
1061
1062
1063
1064
1065
1066 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1067 reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
1068 { return reverse_iterator(this->begin()); }
1069
1070
1071
1072
1073
1074
1075
1076 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1077 const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
1078 { return const_reverse_iterator(this->begin()); }
1079
1080
1081
1082
1083
1084
1085 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1086 const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1087 { return this->begin(); }
1088
1089
1090
1091
1092
1093
1094 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1095 const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
1096 { return this->end(); }
1097
1098
1099
1100
1101
1102
1103
1104 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1105 const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1106 { return this->rbegin(); }
1107
1108
1109
1110
1111
1112
1113
1114 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1115 const_reverse_iterator crend()const BOOST_NOEXCEPT_OR_NOTHROW
1116 { return this->rend(); }
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1130 bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
1131 { return this->index.size() <= ExtraPointers; }
1132
1133
1134
1135
1136
1137
1138 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1139 size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
1140 {
1141 const size_type index_size = this->index.size();
1142 return (index_size - ExtraPointers) & (size_type(0u) -size_type(index_size != 0));
1143 }
1144
1145
1146
1147
1148
1149
1150 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1151 size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
1152 { return this->index.max_size() - ExtraPointers; }
1153
1154
1155
1156
1157
1158
1159
1160 void resize(size_type n)
1161 {
1162 typedef value_init_construct_iterator<value_type> value_init_iterator;
1163 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1164 if(n > this->size())
1165 this->insert( this->cend()
1166 , value_init_iterator(n - this->size()), value_init_iterator());
1167 else if(n < this->size())
1168 this->erase(this->cbegin() + difference_type(n), this->cend());
1169 }
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179 void resize(size_type n, default_init_t)
1180 {
1181 typedef default_init_construct_iterator<value_type> default_init_iterator;
1182 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1183 if(n > this->size())
1184 this->insert(this->cend(), default_init_iterator(n - this->size()), default_init_iterator());
1185 else if(n < this->size())
1186 this->erase(this->cbegin() + difference_type(n), this->cend());
1187 }
1188
1189
1190
1191
1192
1193
1194
1195 void resize(size_type n, const T& t)
1196 {
1197 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1198 if(n > this->size())
1199 this->insert(this->cend(), n - this->size(), t);
1200 else if(n < this->size())
1201 this->erase(this->cbegin() + difference_type(n), this->cend());
1202 }
1203
1204
1205
1206
1207
1208
1209
1210 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1211 size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
1212 {
1213 const size_type index_size = this->index.size();
1214 BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
1215 const size_type node_extra_capacity = this->internal_data.pool_size;
1216
1217 BOOST_ASSERT(node_extra_capacity <= (this->index.capacity()- index_size));
1218 const size_type index_offset =
1219 (node_extra_capacity - ExtraPointers) & (size_type(0u) - size_type(index_size != 0));
1220 return index_size + index_offset;
1221 }
1222
1223
1224
1225
1226
1227
1228
1229 void reserve(size_type n)
1230 {
1231 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1232 if(n > this->max_size()){
1233 throw_length_error("stable_vector::reserve max_size() exceeded");
1234 }
1235
1236 size_type sz = this->size();
1237 size_type old_capacity = this->capacity();
1238 if(n > old_capacity){
1239 index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, n);
1240 const void * old_ptr = &index[0];
1241 this->index.reserve(n + ExtraPointers);
1242 bool realloced = &index[0] != old_ptr;
1243
1244 if(realloced){
1245 index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
1246 }
1247
1248 if((n - sz) > this->internal_data.pool_size){
1249 this->priv_increase_pool((n - sz) - this->internal_data.pool_size);
1250 }
1251 }
1252 }
1253
1254
1255
1256
1257
1258
1259
1260 void shrink_to_fit()
1261 {
1262 if(this->capacity()){
1263
1264 this->priv_clear_pool();
1265
1266 if(this->empty()){
1267 this->index.clear();
1268 this->index.shrink_to_fit();
1269 this->internal_data.end_node.up = node_base_ptr_ptr();
1270 }
1271
1272 else{
1273 const void* old_ptr = &index[0];
1274 this->index.shrink_to_fit();
1275 bool realloced = &index[0] != old_ptr;
1276
1277 if(realloced){
1278 index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
1279 }
1280 }
1281 }
1282 }
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1299 reference front() BOOST_NOEXCEPT_OR_NOTHROW
1300 {
1301 BOOST_ASSERT(!this->empty());
1302 return static_cast<node_reference>(*this->index.front()).get_data();
1303 }
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1314 const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
1315 {
1316 BOOST_ASSERT(!this->empty());
1317 return static_cast<const_node_reference>(*this->index.front()).get_data();
1318 }
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1329 reference back() BOOST_NOEXCEPT_OR_NOTHROW
1330 {
1331 BOOST_ASSERT(!this->empty());
1332 return static_cast<node_reference>(*this->index[this->size()-1u]).get_data();
1333 }
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1344 const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
1345 {
1346 BOOST_ASSERT(!this->empty());
1347 return static_cast<const_node_reference>(*this->index[this->size()-1u]).get_data();
1348 }
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1359 reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1360 {
1361 BOOST_ASSERT(this->size() > n);
1362 return static_cast<node_reference>(*this->index[n]).get_data();
1363 }
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1374 const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1375 {
1376 BOOST_ASSERT(this->size() > n);
1377 return static_cast<const_node_reference>(*this->index[n]).get_data();
1378 }
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1392 iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1393 {
1394 BOOST_ASSERT(this->size() >= n);
1395 return (this->index.empty()) ? this->end() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
1396 }
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1410 const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1411 {
1412 BOOST_ASSERT(this->size() >= n);
1413 return (this->index.empty()) ? this->cend() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
1414 }
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1427 size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1428 { return this->priv_index_of(p.node_pointer()); }
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1441 size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
1442 { return this->priv_index_of(p.node_pointer()); }
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1453 reference at(size_type n)
1454 {
1455 if(n >= this->size()){
1456 throw_out_of_range("vector::at invalid subscript");
1457 }
1458 return operator[](n);
1459 }
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1470 const_reference at(size_type n)const
1471 {
1472 if(n >= this->size()){
1473 throw_out_of_range("vector::at invalid subscript");
1474 }
1475 return operator[](n);
1476 }
1477
1478
1479
1480
1481
1482
1483
1484 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494 template<class ...Args>
1495 reference emplace_back(Args &&...args)
1496 {
1497 typedef emplace_functor<Args...> EmplaceFunctor;
1498 typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;
1499 EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
1500 return *this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
1501 }
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512 template<class ...Args>
1513 iterator emplace(const_iterator p, Args && ...args)
1514 {
1515 BOOST_ASSERT(this->priv_in_range_or_end(p));
1516 difference_type pos_n = p - cbegin();
1517 typedef emplace_functor<Args...> EmplaceFunctor;
1518 typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;
1519 EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
1520 this->insert(p, EmplaceIterator(ef), EmplaceIterator());
1521 return iterator(this->begin() + pos_n);
1522 }
1523
1524 #else
1525
1526 #define BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE(N) \
1527 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1528 reference emplace_back(BOOST_MOVE_UREF##N)\
1529 {\
1530 typedef emplace_functor##N\
1531 BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\
1532 typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;\
1533 EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\
1534 return *this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator());\
1535 }\
1536 \
1537 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1538 iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1539 {\
1540 BOOST_ASSERT(this->priv_in_range_or_end(p));\
1541 typedef emplace_functor##N\
1542 BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\
1543 typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;\
1544 EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\
1545 const size_type pos_n = size_type(p - this->cbegin());\
1546 this->insert(p, EmplaceIterator(ef), EmplaceIterator());\
1547 return this->begin() += difference_type(pos_n);\
1548 }\
1549
1550 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE)
1551 #undef BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE
1552
1553 #endif
1554
1555 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1556
1557
1558
1559
1560
1561
1562 void push_back(const T &x);
1563
1564
1565
1566
1567
1568
1569
1570 void push_back(T &&x);
1571 #else
1572 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
1573 #endif
1574
1575 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586 iterator insert(const_iterator p, const T &x);
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598 iterator insert(const_iterator p, T &&x);
1599 #else
1600 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
1601 #endif
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612 iterator insert(const_iterator p, size_type n, const T& t)
1613 {
1614 BOOST_ASSERT(this->priv_in_range_or_end(p));
1615 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1616 typedef constant_iterator<value_type> cvalue_iterator;
1617 return this->insert(p, cvalue_iterator(t, n), cvalue_iterator());
1618 }
1619
1620
1621 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1622
1623
1624
1625
1626
1627
1628
1629 BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, std::initializer_list<value_type> il)
1630 {
1631
1632 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1633 return insert(p, il.begin(), il.end());
1634 }
1635 #endif
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647 template <class InputIterator>
1648 iterator insert(const_iterator p, InputIterator first, InputIterator last
1649 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1650
1651
1652 , typename dtl::disable_if_or
1653 < void
1654 , dtl::is_convertible<InputIterator, size_type>
1655 , dtl::is_not_input_iterator<InputIterator>
1656 >::type* = 0
1657 #endif
1658 )
1659 {
1660 BOOST_ASSERT(this->priv_in_range_or_end(p));
1661 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1662 const difference_type pos_n = p - this->cbegin();
1663 for(; first != last; ++first){
1664 this->emplace(p, *first);
1665 }
1666 return this->begin() + difference_type(pos_n);
1667 }
1668
1669 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1670 template <class FwdIt>
1671 typename dtl::disable_if_or
1672 < iterator
1673 , dtl::is_convertible<FwdIt, size_type>
1674 , dtl::is_input_iterator<FwdIt>
1675 >::type
1676 insert(const_iterator p, FwdIt first, FwdIt last)
1677 {
1678 BOOST_ASSERT(this->priv_in_range_or_end(p));
1679 const size_type num_new = boost::container::iterator_udistance(first, last);
1680 const size_type idx = static_cast<size_type>(p - this->cbegin());
1681 if(num_new){
1682
1683
1684
1685
1686 index_iterator it_past_newly_constructed(this->priv_insert_forward_non_templated(idx, num_new));
1687 const index_iterator it_past_new(it_past_newly_constructed + difference_type(num_new));
1688 {
1689
1690 insert_rollback rollback(*this, it_past_newly_constructed, it_past_new);
1691 while(first != last){
1692 const node_ptr n = this->priv_get_from_pool();
1693 BOOST_ASSERT(!!n);
1694
1695 *it_past_newly_constructed = n;
1696
1697 this->priv_build_node_from_it(n, it_past_newly_constructed, first);
1698 ++first;
1699 ++it_past_newly_constructed;
1700 }
1701
1702 }
1703
1704
1705 index_traits_type::fix_up_pointers_from(this->index, it_past_newly_constructed);
1706 }
1707 return this->begin() + static_cast<difference_type>(idx);
1708 }
1709 #endif
1710
1711
1712
1713
1714
1715
1716 BOOST_CONTAINER_FORCEINLINE void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
1717 {
1718 BOOST_ASSERT(!this->empty());
1719 this->erase(--this->cend());
1720 }
1721
1722
1723
1724
1725
1726
1727
1728 BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1729 {
1730 BOOST_ASSERT(this->priv_in_range(p));
1731 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1732 const difference_type d = p - this->cbegin();
1733 index_iterator it = this->index.begin() + d;
1734 this->priv_delete_node(p.node_pointer());
1735 it = this->index.erase(it);
1736 index_traits_type::fix_up_pointers_from(this->index, it);
1737 return iterator(node_ptr_traits::static_cast_from(*it));
1738 }
1739
1740
1741
1742
1743
1744
1745
1746 iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
1747 {
1748 BOOST_ASSERT(first == last ||
1749 (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last)));
1750 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1751 const const_iterator cbeg(this->cbegin());
1752 const size_type d1 = static_cast<size_type>(first - cbeg),
1753 d2 = static_cast<size_type>(last - cbeg);
1754 size_type d_dif = d2 - d1;
1755 if(d_dif){
1756 multiallocation_chain holder;
1757 const index_iterator it1(this->index.begin() + difference_type(d1));
1758 const index_iterator it2(it1 + difference_type(d_dif));
1759 index_iterator it(it1);
1760 while(d_dif){
1761 --d_dif;
1762 node_base_ptr &nb = *it;
1763 ++it;
1764 node_type &n = *node_ptr_traits::static_cast_from(nb);
1765 this->priv_destroy_node(n);
1766 holder.push_back(node_ptr_traits::pointer_to(n));
1767 }
1768 this->priv_put_in_pool(holder);
1769 const index_iterator e = this->index.erase(it1, it2);
1770 index_traits_type::fix_up_pointers_from(this->index, e);
1771 }
1772 return iterator(last.node_pointer());
1773 }
1774
1775
1776
1777
1778
1779
1780 void swap(stable_vector & x)
1781 BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
1782 || allocator_traits_type::is_always_equal::value)
1783 {
1784 BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value ||
1785 allocator_traits_type::is_always_equal::value ||
1786 this->get_stored_allocator() == x.get_stored_allocator());
1787 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1788 dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
1789 dtl::swap_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
1790
1791 this->index.swap(x.index);
1792 this->priv_swap_members(x);
1793 }
1794
1795
1796
1797
1798
1799
1800 BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
1801 { this->erase(this->cbegin(),this->cend()); }
1802
1803
1804
1805
1806 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1807 friend bool operator==(const stable_vector& x, const stable_vector& y)
1808 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
1809
1810
1811
1812
1813 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1814 friend bool operator!=(const stable_vector& x, const stable_vector& y)
1815 { return !(x == y); }
1816
1817
1818
1819
1820 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1821 friend bool operator<(const stable_vector& x, const stable_vector& y)
1822 { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
1823
1824
1825
1826
1827 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1828 friend bool operator>(const stable_vector& x, const stable_vector& y)
1829 { return y < x; }
1830
1831
1832
1833
1834 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1835 friend bool operator<=(const stable_vector& x, const stable_vector& y)
1836 { return !(y < x); }
1837
1838
1839
1840
1841 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1842 friend bool operator>=(const stable_vector& x, const stable_vector& y)
1843 { return !(x < y); }
1844
1845
1846
1847
1848 BOOST_CONTAINER_FORCEINLINE friend void swap(stable_vector& x, stable_vector& y)
1849 BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
1850 { x.swap(y); }
1851
1852 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1853 private:
1854
1855 bool priv_in_range(const_iterator pos) const
1856 {
1857 return (this->begin() <= pos) && (pos < this->end());
1858 }
1859
1860 BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const
1861 {
1862 return (this->begin() <= pos) && (pos <= this->end());
1863 }
1864
1865 BOOST_CONTAINER_FORCEINLINE size_type priv_index_of(node_ptr p) const
1866 {
1867
1868 BOOST_ASSERT(this->index.empty() || (this->index.data() <= p->up));
1869 BOOST_ASSERT(this->index.empty() || p->up <= (this->index.data() + this->index.size()));
1870 return this->index.empty() ? 0u : size_type(p->up - this->index.data());
1871 }
1872
1873 class insert_rollback
1874 {
1875 public:
1876
1877 insert_rollback(stable_vector &sv, index_iterator &it_past_constructed, const index_iterator &it_past_new)
1878 : m_sv(sv), m_it_past_constructed(it_past_constructed), m_it_past_new(it_past_new)
1879 {}
1880
1881 ~insert_rollback()
1882 {
1883 if(m_it_past_constructed != m_it_past_new){
1884 m_sv.priv_put_in_pool(node_ptr_traits::static_cast_from(*m_it_past_constructed));
1885 index_iterator e = m_sv.index.erase(m_it_past_constructed, m_it_past_new);
1886 index_traits_type::fix_up_pointers_from(m_sv.index, e);
1887 }
1888 }
1889
1890 private:
1891 stable_vector &m_sv;
1892 index_iterator &m_it_past_constructed;
1893 const index_iterator &m_it_past_new;
1894 };
1895
1896 class push_back_rollback
1897 {
1898 public:
1899 BOOST_CONTAINER_FORCEINLINE push_back_rollback(stable_vector &sv, const node_ptr &p)
1900 : m_sv(sv), m_p(p)
1901 {}
1902
1903 BOOST_CONTAINER_FORCEINLINE ~push_back_rollback()
1904 {
1905 if(m_p){
1906 m_sv.priv_put_in_pool(m_p);
1907 }
1908 }
1909
1910 BOOST_CONTAINER_FORCEINLINE void release()
1911 { m_p = node_ptr(); }
1912
1913 private:
1914 stable_vector &m_sv;
1915 node_ptr m_p;
1916 };
1917
1918 index_iterator priv_insert_forward_non_templated(size_type idx, size_type num_new)
1919 {
1920 index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, num_new);
1921
1922
1923 if(this->internal_data.pool_size < num_new){
1924 this->priv_increase_pool(num_new - this->internal_data.pool_size);
1925 }
1926
1927
1928 const node_base_ptr_ptr old_buffer = this->index.data();
1929 this->index.insert(this->index.begin() + (difference_type)idx, num_new, node_ptr());
1930 bool new_buffer = this->index.data() != old_buffer;
1931
1932
1933 const index_iterator index_beg = this->index.begin();
1934 if(new_buffer){
1935 index_traits_type::fix_up_pointers(index_beg, index_beg + (difference_type)idx);
1936 }
1937 return index_beg + (difference_type)idx;
1938 }
1939
1940 BOOST_CONTAINER_FORCEINLINE bool priv_capacity_bigger_than_size() const
1941 {
1942 return this->index.capacity() > this->index.size() &&
1943 this->internal_data.pool_size > 0;
1944 }
1945
1946 template <class U>
1947 void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
1948 {
1949 if(BOOST_LIKELY(this->priv_capacity_bigger_than_size())){
1950
1951 const node_ptr p = this->priv_get_from_pool();
1952 BOOST_ASSERT(!!p);
1953 {
1954 push_back_rollback rollback(*this, p);
1955
1956 this->priv_build_node_from_convertible(p, ::boost::forward<U>(x));
1957 rollback.release();
1958 }
1959
1960 index_iterator new_index = this->index.insert(this->index.end() - ExtraPointers, p);
1961 index_traits_type::fix_up_pointers_from(this->index, new_index);
1962 }
1963 else{
1964 this->insert(this->cend(), ::boost::forward<U>(x));
1965 }
1966 }
1967
1968 iterator priv_insert(const_iterator p, const value_type &t)
1969 {
1970 BOOST_ASSERT(this->priv_in_range_or_end(p));
1971 typedef constant_iterator<value_type> cvalue_iterator;
1972 return this->insert(p, cvalue_iterator(t, 1), cvalue_iterator());
1973 }
1974
1975 iterator priv_insert(const_iterator p, BOOST_RV_REF(T) x)
1976 {
1977 BOOST_ASSERT(this->priv_in_range_or_end(p));
1978 typedef repeat_iterator<T> repeat_it;
1979 typedef boost::move_iterator<repeat_it> repeat_move_it;
1980
1981 return this->insert(p, repeat_move_it(repeat_it(x, 1)), repeat_move_it(repeat_it()));
1982 }
1983
1984 void priv_clear_pool()
1985 {
1986 if(!this->index.empty() && this->index.back()){
1987 node_base_ptr &pool_first_ref = *(this->index.end() - 2);
1988 node_base_ptr &pool_last_ref = this->index.back();
1989
1990 multiallocation_chain holder;
1991 holder.incorporate_after( holder.before_begin()
1992 , node_ptr_traits::static_cast_from(pool_first_ref)
1993 , node_ptr_traits::static_cast_from(pool_last_ref)
1994 , internal_data.pool_size);
1995 this->deallocate_individual(holder);
1996 pool_first_ref = pool_last_ref = 0;
1997 this->internal_data.pool_size = 0;
1998 }
1999 }
2000
2001 void priv_increase_pool(size_type n)
2002 {
2003 node_base_ptr &pool_first_ref = *(this->index.end() - 2);
2004 node_base_ptr &pool_last_ref = this->index.back();
2005 multiallocation_chain holder;
2006 holder.incorporate_after( holder.before_begin()
2007 , node_ptr_traits::static_cast_from(pool_first_ref)
2008 , node_ptr_traits::static_cast_from(pool_last_ref)
2009 , internal_data.pool_size);
2010 multiallocation_chain m;
2011 this->allocate_individual(n, m);
2012 holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
2013 this->internal_data.pool_size += n;
2014 typename multiallocation_chain::pointer_pair data(holder.extract_data());
2015 pool_first_ref = data.first;
2016 pool_last_ref = data.second;
2017 }
2018
2019 void priv_put_in_pool(const node_ptr &p)
2020 {
2021 node_base_ptr &pool_first_ref = *(this->index.end()-2);
2022 node_base_ptr &pool_last_ref = this->index.back();
2023 multiallocation_chain holder;
2024 holder.incorporate_after( holder.before_begin()
2025 , node_ptr_traits::static_cast_from(pool_first_ref)
2026 , node_ptr_traits::static_cast_from(pool_last_ref)
2027 , internal_data.pool_size);
2028 holder.push_front(p);
2029 ++this->internal_data.pool_size;
2030 typename multiallocation_chain::pointer_pair ret(holder.extract_data());
2031 pool_first_ref = ret.first;
2032 pool_last_ref = ret.second;
2033 }
2034
2035 void priv_put_in_pool(multiallocation_chain &ch)
2036 {
2037 node_base_ptr &pool_first_ref = *(this->index.end()-(ExtraPointers-1));
2038 node_base_ptr &pool_last_ref = this->index.back();
2039 ch.incorporate_after( ch.before_begin()
2040 , node_ptr_traits::static_cast_from(pool_first_ref)
2041 , node_ptr_traits::static_cast_from(pool_last_ref)
2042 , internal_data.pool_size);
2043 this->internal_data.pool_size = ch.size();
2044 const typename multiallocation_chain::pointer_pair ret(ch.extract_data());
2045 pool_first_ref = ret.first;
2046 pool_last_ref = ret.second;
2047 }
2048
2049 node_ptr priv_get_from_pool()
2050 {
2051
2052 BOOST_ASSERT(!this->index.empty());
2053 node_base_ptr &pool_first_ref = *(this->index.end() - (ExtraPointers-1));
2054 node_base_ptr &pool_last_ref = this->index.back();
2055 multiallocation_chain holder;
2056 holder.incorporate_after( holder.before_begin()
2057 , node_ptr_traits::static_cast_from(pool_first_ref)
2058 , node_ptr_traits::static_cast_from(pool_last_ref)
2059 , internal_data.pool_size);
2060 node_ptr ret = holder.pop_front();
2061 --this->internal_data.pool_size;
2062 if(!internal_data.pool_size){
2063 pool_first_ref = pool_last_ref = node_ptr();
2064 }
2065 else{
2066 const typename multiallocation_chain::pointer_pair data(holder.extract_data());
2067 pool_first_ref = data.first;
2068 pool_last_ref = data.second;
2069 }
2070 return ret;
2071 }
2072
2073 BOOST_CONTAINER_FORCEINLINE node_base_ptr priv_get_end_node() const
2074 { return node_base_ptr_traits::pointer_to(const_cast<node_base_type&>(this->internal_data.end_node)); }
2075
2076 BOOST_CONTAINER_FORCEINLINE void priv_destroy_node(const node_type &n)
2077 {
2078 allocator_traits<node_allocator_type>::
2079 destroy(this->priv_node_alloc(), &n);
2080 }
2081
2082 BOOST_CONTAINER_FORCEINLINE void priv_delete_node(const node_ptr &n)
2083 {
2084 this->priv_destroy_node(*n);
2085 this->priv_put_in_pool(n);
2086 }
2087
2088 template<class Iterator>
2089 void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it)
2090 {
2091 node_type *praw = ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
2092 node_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
2093 BOOST_CONTAINER_TRY{
2094
2095 boost::container::construct_in_place
2096 ( this->priv_node_alloc()
2097 , praw->get_data_ptr()
2098 , it);
2099 }
2100 BOOST_CONTAINER_CATCH(...) {
2101 praw->destroy_header();
2102 this->priv_node_alloc().deallocate(p, 1);
2103 BOOST_CONTAINER_RETHROW
2104 }
2105 BOOST_CONTAINER_CATCH_END
2106 }
2107
2108 template<class ValueConvertible>
2109 void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible)
2110 {
2111 node_type *praw = ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) node_type;
2112 BOOST_CONTAINER_TRY{
2113
2114 boost::container::allocator_traits<node_allocator_type>::construct
2115 ( this->priv_node_alloc()
2116 , p->get_data_ptr()
2117 , ::boost::forward<ValueConvertible>(value_convertible));
2118 }
2119 BOOST_CONTAINER_CATCH(...) {
2120 praw->destroy_header();
2121 this->priv_node_alloc().deallocate(p, 1);
2122 BOOST_CONTAINER_RETHROW
2123 }
2124 BOOST_CONTAINER_CATCH_END
2125 }
2126
2127 void priv_swap_members(stable_vector &x)
2128 {
2129 boost::adl_move_swap(this->internal_data.pool_size, x.internal_data.pool_size);
2130 index_traits_type::readjust_end_node(this->index, this->internal_data.end_node);
2131 index_traits_type::readjust_end_node(x.index, x.internal_data.end_node);
2132 }
2133
2134 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
2135 bool priv_invariant()const
2136 {
2137 index_type & index_ref = const_cast<index_type&>(this->index);
2138
2139 const size_type index_size = this->index.size();
2140 if(!index_size)
2141 return !this->capacity() && !this->size();
2142
2143 if(index_size < ExtraPointers)
2144 return false;
2145
2146 const size_type bucket_extra_capacity = this->index.capacity()- index_size;
2147 const size_type node_extra_capacity = this->internal_data.pool_size;
2148 if(bucket_extra_capacity < node_extra_capacity){
2149 return false;
2150 }
2151
2152 if(this->priv_get_end_node() != *(index.end() - ExtraPointers)){
2153 return false;
2154 }
2155
2156 if(!index_traits_type::invariants(index_ref)){
2157 return false;
2158 }
2159
2160 size_type n = this->capacity() - this->size();
2161 node_base_ptr &pool_first_ref = *(index_ref.end() - (ExtraPointers-1));
2162 node_base_ptr &pool_last_ref = index_ref.back();
2163 multiallocation_chain holder;
2164 holder.incorporate_after( holder.before_begin()
2165 , node_ptr_traits::static_cast_from(pool_first_ref)
2166 , node_ptr_traits::static_cast_from(pool_last_ref)
2167 , internal_data.pool_size);
2168 typename multiallocation_chain::iterator beg(holder.begin()), end(holder.end());
2169 size_type num_pool = 0;
2170 while(beg != end){
2171 ++num_pool;
2172 ++beg;
2173 }
2174 return n >= num_pool && num_pool == internal_data.pool_size;
2175 }
2176
2177 class invariant_checker
2178 {
2179 invariant_checker(const invariant_checker &);
2180 invariant_checker & operator=(const invariant_checker &);
2181 const stable_vector* p;
2182
2183 public:
2184 invariant_checker(const stable_vector& v):p(&v){}
2185 ~invariant_checker(){BOOST_ASSERT(p->priv_invariant());}
2186 void touch(){}
2187 };
2188 #endif
2189
2190 class ebo_holder
2191 : public node_allocator_type
2192 {
2193 private:
2194 BOOST_MOVABLE_BUT_NOT_COPYABLE(ebo_holder)
2195
2196 public:
2197 template<class AllocatorRLValue>
2198 explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
2199 : node_allocator_type(boost::forward<AllocatorRLValue>(a))
2200 , pool_size(0)
2201 , end_node()
2202 {}
2203
2204 ebo_holder()
2205 : node_allocator_type()
2206 , pool_size(0)
2207 , end_node()
2208 {}
2209
2210 size_type pool_size;
2211 node_base_type end_node;
2212 } internal_data;
2213
2214 node_allocator_type &priv_node_alloc() { return internal_data; }
2215 const node_allocator_type &priv_node_alloc() const { return internal_data; }
2216
2217 index_type index;
2218 #endif
2219 };
2220
2221 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
2222
2223 template <typename InputIterator>
2224 stable_vector(InputIterator, InputIterator) ->
2225 stable_vector<typename iterator_traits<InputIterator>::value_type>;
2226
2227 template <typename InputIterator, typename Allocator>
2228 stable_vector(InputIterator, InputIterator, Allocator const&) ->
2229 stable_vector<typename iterator_traits<InputIterator>::value_type, Allocator>;
2230
2231 #endif
2232
2233 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2234
2235 #undef BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
2236
2237 }
2238
2239
2240
2241 template <class T, class Allocator>
2242 struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> >
2243 {
2244 typedef typename boost::container::stable_vector<T, Allocator>::allocator_type allocator_type;
2245 typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
2246 static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
2247 ::boost::has_trivial_destructor_after_move<pointer>::value;
2248 };
2249
2250 namespace container {
2251
2252 #endif
2253
2254 }}
2255
2256 #include <boost/container/detail/config_end.hpp>
2257
2258 #endif