File indexing completed on 2025-09-15 08:31:03
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/launder.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 inline clear_on_destroy(C &c)
0085 : c_(c), do_clear_(true)
0086 {}
0087
0088 inline void release()
0089 { do_clear_ = false; }
0090
0091 inline ~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 inline explicit node_base(const node_base_ptr_ptr &n)
0126 : up(n)
0127 {}
0128
0129 inline 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 inline explicit node(const typename hook_type::node_base_ptr_ptr &n)
0156 : hook_type(n)
0157 {}
0158
0159 inline 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 inline T &get_data()
0169 { return *boost::move_detail::launder_cast<T*>(&this->m_storage); }
0170
0171 inline const T &get_data() const
0172 { return *boost::move_detail::launder_cast<const T*>(&this->m_storage); }
0173
0174 inline T *get_data_ptr()
0175 { return boost::move_detail::launder_cast<T*>(&this->m_storage); }
0176
0177 inline const T *get_data_ptr() const
0178 { return boost::move_detail::launder_cast<const T*>(&this->m_storage); }
0179
0180 inline ~node()
0181 { boost::move_detail::launder_cast<T*>(&this->m_storage)->~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 inline 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 BOOST_STATIC_CONSTEXPR size_type ExtraPointers = 3;
0218
0219
0220
0221
0222
0223
0224 inline 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 inline static index_iterator get_fix_up_end(index_type &index)
0238 { return index.end() - (ExtraPointers - 1); }
0239
0240 inline 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 inline explicit stable_vector_iterator(node_base_ptr p) BOOST_NOEXCEPT_OR_NOTHROW
0331 : m_pn(p)
0332 {}
0333
0334 inline stable_vector_iterator() BOOST_NOEXCEPT_OR_NOTHROW
0335 : m_pn()
0336 {}
0337
0338 inline stable_vector_iterator(const stable_vector_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
0339 : m_pn(other.node_pointer())
0340 {}
0341
0342 inline stable_vector_iterator(const nonconst_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
0343 : m_pn(other.node_pointer())
0344 {}
0345
0346 inline 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 inline
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 inline
0356 reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
0357 { return node_pointer()->get_data(); }
0358
0359 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0360 pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
0361 { return ptr_traits::pointer_to(this->operator*()); }
0362
0363
0364 inline 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 inline stable_vector_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
0372 { stable_vector_iterator tmp(*this); ++*this; return stable_vector_iterator(tmp); }
0373
0374 inline 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 inline 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 inline
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 inline 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 inline
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 inline
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 inline stable_vector_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0412 { *this += -off; return *this; }
0413
0414 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
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 inline
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 inline
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 inline
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 inline
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 inline
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 inline
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 inline
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 inline node_ptr allocate_one()
0558 { return allocator_version_traits_t::allocate_one(this->priv_node_alloc()); }
0559
0560 inline void deallocate_one(const node_ptr &p)
0561 { allocator_version_traits_t::deallocate_one(this->priv_node_alloc(), p); }
0562
0563 inline 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 inline 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
0601
0602
0603 BOOST_CONTAINER_STATIC_ASSERT((dtl::is_same<value_type, typename allocator_traits<allocator_type>::value_type>::value));
0604
0605 BOOST_COPYABLE_AND_MOVABLE(stable_vector)
0606 BOOST_STATIC_CONSTEXPR size_type ExtraPointers = index_traits_type::ExtraPointers;
0607
0608 class insert_rollback;
0609 friend class insert_rollback;
0610
0611 class push_back_rollback;
0612 friend class push_back_rollback;
0613 #endif
0614
0615 public:
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627 inline stable_vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<ValueAllocator>::value)
0628 : internal_data(), index()
0629 {
0630 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0631 }
0632
0633
0634
0635
0636
0637
0638 inline explicit stable_vector(const allocator_type& al) BOOST_NOEXCEPT_OR_NOTHROW
0639 : internal_data(al), index(al)
0640 {
0641 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0642 }
0643
0644
0645
0646
0647
0648
0649
0650
0651 explicit stable_vector(size_type n)
0652 : internal_data(), index()
0653 {
0654 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0655 this->resize(n);
0656 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0657 cod.release();
0658 }
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669 stable_vector(size_type n, default_init_t)
0670 : internal_data(), index()
0671 {
0672 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0673 this->resize(n, default_init);
0674 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0675 cod.release();
0676 }
0677
0678
0679
0680
0681
0682
0683
0684
0685 explicit stable_vector(size_type n, const allocator_type &a)
0686 : internal_data(), index(a)
0687 {
0688 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0689 this->resize(n);
0690 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0691 cod.release();
0692 }
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703 stable_vector(size_type n, default_init_t, const allocator_type &a)
0704 : internal_data(), index(a)
0705 {
0706 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0707 this->resize(n, default_init);
0708 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0709 cod.release();
0710 }
0711
0712
0713
0714
0715
0716
0717
0718
0719 stable_vector(size_type n, const T& t, const allocator_type& al = allocator_type())
0720 : internal_data(al), index(al)
0721 {
0722 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0723 this->insert(this->cend(), n, t);
0724 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0725 cod.release();
0726 }
0727
0728
0729
0730
0731
0732
0733
0734
0735 template <class InputIterator>
0736 stable_vector(InputIterator first,InputIterator last, const allocator_type& al = allocator_type())
0737 : internal_data(al), index(al)
0738 {
0739 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0740 this->insert(this->cend(), first, last);
0741 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0742 cod.release();
0743 }
0744
0745
0746
0747
0748
0749
0750 stable_vector(const stable_vector& x)
0751 : internal_data(allocator_traits<node_allocator_type>::
0752 select_on_container_copy_construction(x.priv_node_alloc()))
0753 , index(allocator_traits<allocator_type>::
0754 select_on_container_copy_construction(x.index.get_stored_allocator()))
0755 {
0756 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0757 this->insert(this->cend(), x.begin(), x.end());
0758 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0759 cod.release();
0760 }
0761
0762 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0763
0764
0765
0766
0767
0768
0769
0770 stable_vector(std::initializer_list<value_type> il, const allocator_type& l = allocator_type())
0771 : internal_data(l), index(l)
0772 {
0773 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0774 insert(cend(), il.begin(), il.end());
0775 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0776 cod.release();
0777 }
0778 #endif
0779
0780
0781
0782
0783
0784
0785 inline stable_vector(BOOST_RV_REF(stable_vector) x) BOOST_NOEXCEPT_OR_NOTHROW
0786 : internal_data(boost::move(x.priv_node_alloc())), index(boost::move(x.index))
0787 {
0788 this->priv_swap_members(x);
0789 }
0790
0791
0792
0793
0794
0795
0796 stable_vector(const stable_vector& x, const allocator_type &a)
0797 : internal_data(a), index(a)
0798 {
0799 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0800 this->insert(this->cend(), x.begin(), x.end());
0801 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0802 cod.release();
0803 }
0804
0805
0806
0807
0808
0809
0810
0811 stable_vector(BOOST_RV_REF(stable_vector) x, const allocator_type &a)
0812 : internal_data(a), index(a)
0813 {
0814 if(this->priv_node_alloc() == x.priv_node_alloc()){
0815 this->index.swap(x.index);
0816 this->priv_swap_members(x);
0817 }
0818 else{
0819 stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
0820 this->insert(this->cend(), boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
0821 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0822 cod.release();
0823 }
0824 }
0825
0826
0827
0828
0829
0830
0831
0832 ~stable_vector()
0833 {
0834 this->clear();
0835 this->priv_clear_pool();
0836 }
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846 stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
0847 {
0848 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0849 if (BOOST_LIKELY(this != &x)) {
0850 node_allocator_type &this_alloc = this->priv_node_alloc();
0851 const node_allocator_type &x_alloc = x.priv_node_alloc();
0852 dtl::bool_<allocator_traits_type::
0853 propagate_on_container_copy_assignment::value> flag;
0854 if(flag && this_alloc != x_alloc){
0855 this->clear();
0856 this->shrink_to_fit();
0857 }
0858 dtl::assign_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
0859 dtl::assign_alloc(this->index.get_stored_allocator(), x.index.get_stored_allocator(), flag);
0860 this->assign(x.begin(), x.end());
0861 }
0862 return *this;
0863 }
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876 stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
0877 BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
0878 || allocator_traits_type::is_always_equal::value)
0879 {
0880 if (BOOST_LIKELY(this != &x)) {
0881
0882
0883 const bool can_steal_resources_alloc
0884 = allocator_traits_type::propagate_on_container_move_assignment::value
0885 || allocator_traits_type::is_always_equal::value;
0886 dtl::bool_<can_steal_resources_alloc> flag;
0887 this->priv_move_assign(boost::move(x), flag);
0888 }
0889 return *this;
0890 }
0891
0892 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0893
0894
0895
0896 stable_vector& operator=(std::initializer_list<value_type> il)
0897 {
0898 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0899 assign(il.begin(), il.end());
0900 return *this;
0901 }
0902 #endif
0903
0904
0905
0906
0907
0908
0909 inline void assign(size_type n, const T& t)
0910 {
0911 typedef constant_iterator<value_type> cvalue_iterator;
0912 this->assign(cvalue_iterator(t, n), cvalue_iterator());
0913 }
0914
0915
0916
0917
0918
0919
0920
0921 template<typename InputIterator>
0922 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
0923 typename dtl::disable_if_convertible<InputIterator, size_type>::type
0924 #else
0925 void
0926 #endif
0927 assign(InputIterator first,InputIterator last)
0928 {
0929 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0930 iterator first1 = this->begin();
0931 iterator last1 = this->end();
0932 for ( ; first1 != last1 && first != last; ++first1, ++first)
0933 *first1 = *first;
0934 if (first == last){
0935 this->erase(first1, last1);
0936 }
0937 else{
0938 this->insert(last1, first, last);
0939 }
0940 }
0941
0942 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0943
0944
0945
0946
0947
0948 inline void assign(std::initializer_list<value_type> il)
0949 {
0950 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
0951 assign(il.begin(), il.end());
0952 }
0953 #endif
0954
0955
0956
0957
0958
0959
0960 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0961 allocator_type get_allocator() const
0962 { return this->priv_node_alloc(); }
0963
0964
0965
0966
0967
0968
0969
0970
0971 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0972 const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
0973 { return this->priv_node_alloc(); }
0974
0975
0976
0977
0978
0979
0980
0981
0982 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0983 stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
0984 { return this->priv_node_alloc(); }
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995
0996
0997 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0998 iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
0999 { return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); }
1000
1001
1002
1003
1004
1005
1006 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1007 const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
1008 { return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; }
1009
1010
1011
1012
1013
1014
1015 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1016 iterator end() BOOST_NOEXCEPT_OR_NOTHROW
1017 { return iterator(this->priv_get_end_node()); }
1018
1019
1020
1021
1022
1023
1024 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1025 const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
1026 { return const_iterator(this->priv_get_end_node()); }
1027
1028
1029
1030
1031
1032
1033
1034 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1035 reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
1036 { return reverse_iterator(this->end()); }
1037
1038
1039
1040
1041
1042
1043
1044 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1045 const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1046 { return const_reverse_iterator(this->end()); }
1047
1048
1049
1050
1051
1052
1053
1054 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1055 reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
1056 { return reverse_iterator(this->begin()); }
1057
1058
1059
1060
1061
1062
1063
1064 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1065 const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
1066 { return const_reverse_iterator(this->begin()); }
1067
1068
1069
1070
1071
1072
1073 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1074 const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1075 { return this->begin(); }
1076
1077
1078
1079
1080
1081
1082 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1083 const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
1084 { return this->end(); }
1085
1086
1087
1088
1089
1090
1091
1092 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1093 const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1094 { return this->rbegin(); }
1095
1096
1097
1098
1099
1100
1101
1102 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1103 const_reverse_iterator crend()const BOOST_NOEXCEPT_OR_NOTHROW
1104 { return this->rend(); }
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1118 bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
1119 { return this->index.size() <= ExtraPointers; }
1120
1121
1122
1123
1124
1125
1126 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1127 size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
1128 {
1129 const size_type index_size = this->index.size();
1130 return (index_size - ExtraPointers) & (size_type(0u) -size_type(index_size != 0));
1131 }
1132
1133
1134
1135
1136
1137
1138 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1139 size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
1140 { return this->index.max_size() - ExtraPointers; }
1141
1142
1143
1144
1145
1146
1147
1148 void resize(size_type n)
1149 {
1150 typedef value_init_construct_iterator<value_type> value_init_iterator;
1151 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1152 if(n > this->size())
1153 this->insert( this->cend()
1154 , value_init_iterator(n - this->size()), value_init_iterator());
1155 else if(n < this->size())
1156 this->erase(this->cbegin() + difference_type(n), this->cend());
1157 }
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167 void resize(size_type n, default_init_t)
1168 {
1169 typedef default_init_construct_iterator<value_type> default_init_iterator;
1170 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1171 if(n > this->size())
1172 this->insert(this->cend(), default_init_iterator(n - this->size()), default_init_iterator());
1173 else if(n < this->size())
1174 this->erase(this->cbegin() + difference_type(n), this->cend());
1175 }
1176
1177
1178
1179
1180
1181
1182
1183 void resize(size_type n, const T& t)
1184 {
1185 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1186 if(n > this->size())
1187 this->insert(this->cend(), n - this->size(), t);
1188 else if(n < this->size())
1189 this->erase(this->cbegin() + difference_type(n), this->cend());
1190 }
1191
1192
1193
1194
1195
1196
1197
1198 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1199 size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
1200 {
1201 const size_type index_size = this->index.size();
1202 BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
1203 const size_type node_extra_capacity = this->internal_data.pool_size;
1204
1205 BOOST_ASSERT(node_extra_capacity <= (this->index.capacity()- index_size));
1206 const size_type index_offset =
1207 (node_extra_capacity - ExtraPointers) & (size_type(0u) - size_type(index_size != 0));
1208 return index_size + index_offset;
1209 }
1210
1211
1212
1213
1214
1215
1216
1217 void reserve(size_type n)
1218 {
1219 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1220 if(n > this->max_size()){
1221 throw_length_error("stable_vector::reserve max_size() exceeded");
1222 }
1223
1224 size_type sz = this->size();
1225 size_type old_capacity = this->capacity();
1226 if(n > old_capacity){
1227 index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, n);
1228 const void * old_ptr = &index[0];
1229 this->index.reserve(n + ExtraPointers);
1230 bool realloced = &index[0] != old_ptr;
1231
1232 if(realloced){
1233 index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
1234 }
1235
1236 if((n - sz) > this->internal_data.pool_size){
1237 this->priv_increase_pool((n - sz) - this->internal_data.pool_size);
1238 }
1239 }
1240 }
1241
1242
1243
1244
1245
1246
1247
1248 void shrink_to_fit()
1249 {
1250 if(this->capacity()){
1251
1252 this->priv_clear_pool();
1253
1254 if(this->empty()){
1255 this->index.clear();
1256 this->index.shrink_to_fit();
1257 this->internal_data.end_node.up = node_base_ptr_ptr();
1258 }
1259
1260 else{
1261 const void* old_ptr = &index[0];
1262 this->index.shrink_to_fit();
1263 bool realloced = &index[0] != old_ptr;
1264
1265 if(realloced){
1266 index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
1267 }
1268 }
1269 }
1270 }
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1287 reference front() BOOST_NOEXCEPT_OR_NOTHROW
1288 {
1289 BOOST_ASSERT(!this->empty());
1290 return static_cast<node_reference>(*this->index.front()).get_data();
1291 }
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1302 const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
1303 {
1304 BOOST_ASSERT(!this->empty());
1305 return static_cast<const_node_reference>(*this->index.front()).get_data();
1306 }
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1317 reference back() BOOST_NOEXCEPT_OR_NOTHROW
1318 {
1319 BOOST_ASSERT(!this->empty());
1320 return static_cast<node_reference>(*this->index[this->size()-1u]).get_data();
1321 }
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1332 const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
1333 {
1334 BOOST_ASSERT(!this->empty());
1335 return static_cast<const_node_reference>(*this->index[this->size()-1u]).get_data();
1336 }
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1347 reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1348 {
1349 BOOST_ASSERT(this->size() > n);
1350 return static_cast<node_reference>(*this->index[n]).get_data();
1351 }
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1362 const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1363 {
1364 BOOST_ASSERT(this->size() > n);
1365 return static_cast<const_node_reference>(*this->index[n]).get_data();
1366 }
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1380 iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1381 {
1382 BOOST_ASSERT(this->size() >= n);
1383 return (this->index.empty()) ? this->end() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
1384 }
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1398 const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1399 {
1400 BOOST_ASSERT(this->size() >= n);
1401 return (this->index.empty()) ? this->cend() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
1402 }
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1415 size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1416 { return this->priv_index_of(p.node_pointer()); }
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1429 size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
1430 { return this->priv_index_of(p.node_pointer()); }
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1441 reference at(size_type n)
1442 {
1443 if(n >= this->size()){
1444 throw_out_of_range("vector::at invalid subscript");
1445 }
1446 return operator[](n);
1447 }
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1458 const_reference at(size_type n)const
1459 {
1460 if(n >= this->size()){
1461 throw_out_of_range("vector::at invalid subscript");
1462 }
1463 return operator[](n);
1464 }
1465
1466
1467
1468
1469
1470
1471
1472 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482 template<class ...Args>
1483 reference emplace_back(Args &&...args)
1484 {
1485 typedef emplace_functor<Args...> EmplaceFunctor;
1486 typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;
1487 EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
1488 return *this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
1489 }
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500 template<class ...Args>
1501 iterator emplace(const_iterator p, Args && ...args)
1502 {
1503 BOOST_ASSERT(this->priv_in_range_or_end(p));
1504 difference_type pos_n = p - cbegin();
1505 typedef emplace_functor<Args...> EmplaceFunctor;
1506 typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;
1507 EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
1508 this->insert(p, EmplaceIterator(ef), EmplaceIterator());
1509 return iterator(this->begin() + pos_n);
1510 }
1511
1512 #else
1513
1514 #define BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE(N) \
1515 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1516 reference emplace_back(BOOST_MOVE_UREF##N)\
1517 {\
1518 typedef emplace_functor##N\
1519 BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\
1520 typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;\
1521 EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\
1522 return *this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator());\
1523 }\
1524 \
1525 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1526 iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1527 {\
1528 BOOST_ASSERT(this->priv_in_range_or_end(p));\
1529 typedef emplace_functor##N\
1530 BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\
1531 typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;\
1532 EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\
1533 const size_type pos_n = size_type(p - this->cbegin());\
1534 this->insert(p, EmplaceIterator(ef), EmplaceIterator());\
1535 return this->begin() += difference_type(pos_n);\
1536 }\
1537
1538 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE)
1539 #undef BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE
1540
1541 #endif
1542
1543 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1544
1545
1546
1547
1548
1549
1550 void push_back(const T &x);
1551
1552
1553
1554
1555
1556
1557
1558 void push_back(T &&x);
1559 #else
1560 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
1561 #endif
1562
1563 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574 iterator insert(const_iterator p, const T &x);
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586 iterator insert(const_iterator p, T &&x);
1587 #else
1588 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
1589 #endif
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600 iterator insert(const_iterator p, size_type n, const T& t)
1601 {
1602 BOOST_ASSERT(this->priv_in_range_or_end(p));
1603 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1604 typedef constant_iterator<value_type> cvalue_iterator;
1605 return this->insert(p, cvalue_iterator(t, n), cvalue_iterator());
1606 }
1607
1608
1609 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1610
1611
1612
1613
1614
1615
1616
1617 inline iterator insert(const_iterator p, std::initializer_list<value_type> il)
1618 {
1619
1620 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1621 return insert(p, il.begin(), il.end());
1622 }
1623 #endif
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635 template <class InputIterator>
1636 iterator insert(const_iterator p, InputIterator first, InputIterator last
1637 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1638
1639
1640 , typename dtl::disable_if_or
1641 < void
1642 , dtl::is_convertible<InputIterator, size_type>
1643 , dtl::is_not_input_iterator<InputIterator>
1644 >::type* = 0
1645 #endif
1646 )
1647 {
1648 BOOST_ASSERT(this->priv_in_range_or_end(p));
1649 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1650 const difference_type pos_n = p - this->cbegin();
1651 for(; first != last; ++first){
1652 this->emplace(p, *first);
1653 }
1654 return this->begin() + difference_type(pos_n);
1655 }
1656
1657 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1658 template <class FwdIt>
1659 typename dtl::disable_if_or
1660 < iterator
1661 , dtl::is_convertible<FwdIt, size_type>
1662 , dtl::is_input_iterator<FwdIt>
1663 >::type
1664 insert(const_iterator p, FwdIt first, FwdIt last)
1665 {
1666 BOOST_ASSERT(this->priv_in_range_or_end(p));
1667 const size_type num_new = boost::container::iterator_udistance(first, last);
1668 const size_type idx = static_cast<size_type>(p - this->cbegin());
1669 if(num_new){
1670
1671
1672
1673
1674 index_iterator it_past_newly_constructed(this->priv_insert_forward_non_templated(idx, num_new));
1675 const index_iterator it_past_new(it_past_newly_constructed + difference_type(num_new));
1676 {
1677
1678 insert_rollback rollback(*this, it_past_newly_constructed, it_past_new);
1679 while(first != last){
1680 const node_ptr n = this->priv_get_from_pool();
1681 BOOST_ASSERT(!!n);
1682
1683 *it_past_newly_constructed = n;
1684
1685 this->priv_build_node_from_it(n, it_past_newly_constructed, first);
1686 ++first;
1687 ++it_past_newly_constructed;
1688 }
1689
1690 }
1691
1692
1693 index_traits_type::fix_up_pointers_from(this->index, it_past_newly_constructed);
1694 }
1695 return this->begin() + static_cast<difference_type>(idx);
1696 }
1697 #endif
1698
1699
1700
1701
1702
1703
1704 inline void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
1705 {
1706 BOOST_ASSERT(!this->empty());
1707 this->erase(--this->cend());
1708 }
1709
1710
1711
1712
1713
1714
1715
1716 inline iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1717 {
1718 BOOST_ASSERT(this->priv_in_range(p));
1719 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1720 const difference_type d = p - this->cbegin();
1721 index_iterator it = this->index.begin() + d;
1722 this->priv_delete_node(p.node_pointer());
1723 it = this->index.erase(it);
1724 index_traits_type::fix_up_pointers_from(this->index, it);
1725 return iterator(node_ptr_traits::static_cast_from(*it));
1726 }
1727
1728
1729
1730
1731
1732
1733
1734 iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
1735 {
1736 BOOST_ASSERT(first == last ||
1737 (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last)));
1738 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1739 const const_iterator cbeg(this->cbegin());
1740 const size_type d1 = static_cast<size_type>(first - cbeg),
1741 d2 = static_cast<size_type>(last - cbeg);
1742 size_type d_dif = d2 - d1;
1743 if(d_dif){
1744 multiallocation_chain holder;
1745 const index_iterator it1(this->index.begin() + difference_type(d1));
1746 const index_iterator it2(it1 + difference_type(d_dif));
1747 index_iterator it(it1);
1748 while(d_dif){
1749 --d_dif;
1750 node_base_ptr &nb = *it;
1751 ++it;
1752 node_type &n = *node_ptr_traits::static_cast_from(nb);
1753 this->priv_destroy_node(n);
1754 holder.push_back(node_ptr_traits::pointer_to(n));
1755 }
1756 this->priv_put_in_pool(holder);
1757 const index_iterator e = this->index.erase(it1, it2);
1758 index_traits_type::fix_up_pointers_from(this->index, e);
1759 }
1760 return iterator(last.node_pointer());
1761 }
1762
1763
1764
1765
1766
1767
1768 void swap(stable_vector & x)
1769 BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
1770 || allocator_traits_type::is_always_equal::value)
1771 {
1772 BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value ||
1773 allocator_traits_type::is_always_equal::value ||
1774 this->get_stored_allocator() == x.get_stored_allocator());
1775 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
1776 dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
1777 dtl::swap_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
1778
1779 this->index.swap(x.index);
1780 this->priv_swap_members(x);
1781 }
1782
1783
1784
1785
1786
1787
1788 inline void clear() BOOST_NOEXCEPT_OR_NOTHROW
1789 { this->erase(this->cbegin(),this->cend()); }
1790
1791
1792
1793
1794 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1795 friend bool operator==(const stable_vector& x, const stable_vector& y)
1796 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
1797
1798
1799
1800
1801 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1802 friend bool operator!=(const stable_vector& x, const stable_vector& y)
1803 { return !(x == y); }
1804
1805
1806
1807
1808 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1809 friend bool operator<(const stable_vector& x, const stable_vector& y)
1810 { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
1811
1812
1813
1814
1815 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1816 friend bool operator>(const stable_vector& x, const stable_vector& y)
1817 { return y < x; }
1818
1819
1820
1821
1822 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1823 friend bool operator<=(const stable_vector& x, const stable_vector& y)
1824 { return !(y < x); }
1825
1826
1827
1828
1829 BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1830 friend bool operator>=(const stable_vector& x, const stable_vector& y)
1831 { return !(x < y); }
1832
1833
1834
1835
1836 inline friend void swap(stable_vector& x, stable_vector& y)
1837 BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
1838 { x.swap(y); }
1839
1840 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1841 private:
1842
1843 void priv_move_assign(BOOST_RV_REF(stable_vector) x, dtl::bool_<true> )
1844 {
1845
1846
1847 BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
1848
1849 this->clear();
1850
1851 dtl::bool_<allocator_traits_type::
1852 propagate_on_container_move_assignment::value> flag;
1853 dtl::move_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
1854
1855
1856 this->index = boost::move(x.index);
1857 this->priv_swap_members(x);
1858 }
1859
1860 void priv_move_assign(BOOST_RV_REF(stable_vector) x, dtl::bool_<false> )
1861 {
1862
1863
1864 if (this->priv_node_alloc() == x.priv_node_alloc()) {
1865 this->priv_move_assign(boost::move(x), dtl::true_());
1866 }
1867 else {
1868 this->assign(boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
1869 }
1870 }
1871
1872 bool priv_in_range(const_iterator pos) const
1873 {
1874 return (this->begin() <= pos) && (pos < this->end());
1875 }
1876
1877 inline bool priv_in_range_or_end(const_iterator pos) const
1878 {
1879 return (this->begin() <= pos) && (pos <= this->end());
1880 }
1881
1882 inline size_type priv_index_of(node_ptr p) const
1883 {
1884
1885 BOOST_ASSERT(this->index.empty() || (this->index.data() <= p->up));
1886 BOOST_ASSERT(this->index.empty() || p->up <= (this->index.data() + this->index.size()));
1887 return this->index.empty() ? 0u : size_type(p->up - this->index.data());
1888 }
1889
1890 class insert_rollback
1891 {
1892 public:
1893
1894 insert_rollback(stable_vector &sv, index_iterator &it_past_constructed, const index_iterator &it_past_new)
1895 : m_sv(sv), m_it_past_constructed(it_past_constructed), m_it_past_new(it_past_new)
1896 {}
1897
1898 ~insert_rollback()
1899 {
1900 if(m_it_past_constructed != m_it_past_new){
1901 m_sv.priv_put_in_pool(node_ptr_traits::static_cast_from(*m_it_past_constructed));
1902 index_iterator e = m_sv.index.erase(m_it_past_constructed, m_it_past_new);
1903 index_traits_type::fix_up_pointers_from(m_sv.index, e);
1904 }
1905 }
1906
1907 private:
1908 stable_vector &m_sv;
1909 index_iterator &m_it_past_constructed;
1910 const index_iterator &m_it_past_new;
1911 };
1912
1913 class push_back_rollback
1914 {
1915 public:
1916 inline push_back_rollback(stable_vector &sv, const node_ptr &p)
1917 : m_sv(sv), m_p(p)
1918 {}
1919
1920 inline ~push_back_rollback()
1921 {
1922 if(m_p){
1923 m_sv.priv_put_in_pool(m_p);
1924 }
1925 }
1926
1927 inline void release()
1928 { m_p = node_ptr(); }
1929
1930 private:
1931 stable_vector &m_sv;
1932 node_ptr m_p;
1933 };
1934
1935 index_iterator priv_insert_forward_non_templated(size_type idx, size_type num_new)
1936 {
1937 index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, num_new);
1938
1939
1940 if(this->internal_data.pool_size < num_new){
1941 this->priv_increase_pool(num_new - this->internal_data.pool_size);
1942 }
1943
1944
1945 const node_base_ptr_ptr old_buffer = this->index.data();
1946 this->index.insert(this->index.begin() + (difference_type)idx, num_new, node_ptr());
1947 bool new_buffer = this->index.data() != old_buffer;
1948
1949
1950 const index_iterator index_beg = this->index.begin();
1951 if(new_buffer){
1952 index_traits_type::fix_up_pointers(index_beg, index_beg + (difference_type)idx);
1953 }
1954 return index_beg + (difference_type)idx;
1955 }
1956
1957 inline bool priv_capacity_bigger_than_size() const
1958 {
1959 return this->index.capacity() > this->index.size() &&
1960 this->internal_data.pool_size > 0;
1961 }
1962
1963 template <class U>
1964 void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
1965 {
1966 if(BOOST_LIKELY(this->priv_capacity_bigger_than_size())){
1967
1968 const node_ptr p = this->priv_get_from_pool();
1969 BOOST_ASSERT(!!p);
1970 {
1971 push_back_rollback rollback(*this, p);
1972
1973 this->priv_build_node_from_convertible(p, ::boost::forward<U>(x));
1974 rollback.release();
1975 }
1976
1977 index_iterator new_index = this->index.insert(this->index.end() - ExtraPointers, p);
1978 index_traits_type::fix_up_pointers_from(this->index, new_index);
1979 }
1980 else{
1981 this->insert(this->cend(), ::boost::forward<U>(x));
1982 }
1983 }
1984
1985 iterator priv_insert(const_iterator p, const value_type &t)
1986 {
1987 BOOST_ASSERT(this->priv_in_range_or_end(p));
1988 typedef constant_iterator<value_type> cvalue_iterator;
1989 return this->insert(p, cvalue_iterator(t, 1), cvalue_iterator());
1990 }
1991
1992 iterator priv_insert(const_iterator p, BOOST_RV_REF(T) x)
1993 {
1994 BOOST_ASSERT(this->priv_in_range_or_end(p));
1995 typedef repeat_iterator<T> repeat_it;
1996 typedef boost::move_iterator<repeat_it> repeat_move_it;
1997
1998 return this->insert(p, repeat_move_it(repeat_it(x, 1)), repeat_move_it(repeat_it()));
1999 }
2000
2001 void priv_clear_pool()
2002 {
2003 if(!this->index.empty() && this->index.back()){
2004 node_base_ptr &pool_first_ref = *(this->index.end() - 2);
2005 node_base_ptr &pool_last_ref = this->index.back();
2006
2007 multiallocation_chain holder;
2008 holder.incorporate_after( holder.before_begin()
2009 , node_ptr_traits::static_cast_from(pool_first_ref)
2010 , node_ptr_traits::static_cast_from(pool_last_ref)
2011 , internal_data.pool_size);
2012 this->deallocate_individual(holder);
2013 pool_first_ref = pool_last_ref = 0;
2014 this->internal_data.pool_size = 0;
2015 }
2016 }
2017
2018 void priv_increase_pool(size_type n)
2019 {
2020 node_base_ptr &pool_first_ref = *(this->index.end() - 2);
2021 node_base_ptr &pool_last_ref = this->index.back();
2022 multiallocation_chain holder;
2023 holder.incorporate_after( holder.before_begin()
2024 , node_ptr_traits::static_cast_from(pool_first_ref)
2025 , node_ptr_traits::static_cast_from(pool_last_ref)
2026 , internal_data.pool_size);
2027 multiallocation_chain m;
2028 this->allocate_individual(n, m);
2029 holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
2030 this->internal_data.pool_size += n;
2031 typename multiallocation_chain::pointer_pair data(holder.extract_data());
2032 pool_first_ref = data.first;
2033 pool_last_ref = data.second;
2034 }
2035
2036 void priv_put_in_pool(const node_ptr &p)
2037 {
2038 node_base_ptr &pool_first_ref = *(this->index.end()-2);
2039 node_base_ptr &pool_last_ref = this->index.back();
2040 multiallocation_chain holder;
2041 holder.incorporate_after( holder.before_begin()
2042 , node_ptr_traits::static_cast_from(pool_first_ref)
2043 , node_ptr_traits::static_cast_from(pool_last_ref)
2044 , internal_data.pool_size);
2045 holder.push_front(p);
2046 ++this->internal_data.pool_size;
2047 typename multiallocation_chain::pointer_pair ret(holder.extract_data());
2048 pool_first_ref = ret.first;
2049 pool_last_ref = ret.second;
2050 }
2051
2052 void priv_put_in_pool(multiallocation_chain &ch)
2053 {
2054 node_base_ptr &pool_first_ref = *(this->index.end()-(ExtraPointers-1));
2055 node_base_ptr &pool_last_ref = this->index.back();
2056 ch.incorporate_after( ch.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 this->internal_data.pool_size = ch.size();
2061 const typename multiallocation_chain::pointer_pair ret(ch.extract_data());
2062 pool_first_ref = ret.first;
2063 pool_last_ref = ret.second;
2064 }
2065
2066 node_ptr priv_get_from_pool()
2067 {
2068
2069 BOOST_ASSERT(!this->index.empty());
2070 node_base_ptr &pool_first_ref = *(this->index.end() - (ExtraPointers-1));
2071 node_base_ptr &pool_last_ref = this->index.back();
2072 multiallocation_chain holder;
2073 holder.incorporate_after( holder.before_begin()
2074 , node_ptr_traits::static_cast_from(pool_first_ref)
2075 , node_ptr_traits::static_cast_from(pool_last_ref)
2076 , internal_data.pool_size);
2077 node_ptr ret = holder.pop_front();
2078 --this->internal_data.pool_size;
2079 if(!internal_data.pool_size){
2080 pool_first_ref = pool_last_ref = node_ptr();
2081 }
2082 else{
2083 const typename multiallocation_chain::pointer_pair data(holder.extract_data());
2084 pool_first_ref = data.first;
2085 pool_last_ref = data.second;
2086 }
2087 return ret;
2088 }
2089
2090 inline node_base_ptr priv_get_end_node() const
2091 { return node_base_ptr_traits::pointer_to(const_cast<node_base_type&>(this->internal_data.end_node)); }
2092
2093 inline void priv_destroy_node(const node_type &n)
2094 {
2095 allocator_traits<node_allocator_type>::
2096 destroy(this->priv_node_alloc(), &n);
2097 }
2098
2099 inline void priv_delete_node(const node_ptr &n)
2100 {
2101 this->priv_destroy_node(*n);
2102 this->priv_put_in_pool(n);
2103 }
2104
2105 template<class Iterator>
2106 void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it)
2107 {
2108 node_type *praw = ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
2109 node_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
2110 BOOST_CONTAINER_TRY{
2111
2112 boost::container::construct_in_place
2113 ( this->priv_node_alloc()
2114 , praw->get_data_ptr()
2115 , it);
2116 }
2117 BOOST_CONTAINER_CATCH(...) {
2118 praw->destroy_header();
2119 this->priv_node_alloc().deallocate(p, 1);
2120 BOOST_CONTAINER_RETHROW
2121 }
2122 BOOST_CONTAINER_CATCH_END
2123 }
2124
2125 template<class ValueConvertible>
2126 void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible)
2127 {
2128 node_type *praw = ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) node_type;
2129 BOOST_CONTAINER_TRY{
2130
2131 boost::container::allocator_traits<node_allocator_type>::construct
2132 ( this->priv_node_alloc()
2133 , p->get_data_ptr()
2134 , ::boost::forward<ValueConvertible>(value_convertible));
2135 }
2136 BOOST_CONTAINER_CATCH(...) {
2137 praw->destroy_header();
2138 this->priv_node_alloc().deallocate(p, 1);
2139 BOOST_CONTAINER_RETHROW
2140 }
2141 BOOST_CONTAINER_CATCH_END
2142 }
2143
2144 void priv_swap_members(stable_vector &x)
2145 {
2146 boost::adl_move_swap(this->internal_data.pool_size, x.internal_data.pool_size);
2147 index_traits_type::readjust_end_node(this->index, this->internal_data.end_node);
2148 index_traits_type::readjust_end_node(x.index, x.internal_data.end_node);
2149 }
2150
2151 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
2152 bool priv_invariant()const
2153 {
2154 index_type & index_ref = const_cast<index_type&>(this->index);
2155
2156 const size_type index_size = this->index.size();
2157 if(!index_size)
2158 return !this->capacity() && !this->size();
2159
2160 if(index_size < ExtraPointers)
2161 return false;
2162
2163 const size_type bucket_extra_capacity = this->index.capacity()- index_size;
2164 const size_type node_extra_capacity = this->internal_data.pool_size;
2165 if(bucket_extra_capacity < node_extra_capacity){
2166 return false;
2167 }
2168
2169 if(this->priv_get_end_node() != *(index.end() - ExtraPointers)){
2170 return false;
2171 }
2172
2173 if(!index_traits_type::invariants(index_ref)){
2174 return false;
2175 }
2176
2177 size_type n = this->capacity() - this->size();
2178 node_base_ptr &pool_first_ref = *(index_ref.end() - (ExtraPointers-1));
2179 node_base_ptr &pool_last_ref = index_ref.back();
2180 multiallocation_chain holder;
2181 holder.incorporate_after( holder.before_begin()
2182 , node_ptr_traits::static_cast_from(pool_first_ref)
2183 , node_ptr_traits::static_cast_from(pool_last_ref)
2184 , internal_data.pool_size);
2185 typename multiallocation_chain::iterator b(holder.begin()), e(holder.end());
2186 size_type num_pool = 0;
2187 while(b != e){
2188 ++num_pool;
2189 ++b;
2190 }
2191 return n >= num_pool && num_pool == internal_data.pool_size;
2192 }
2193
2194 class invariant_checker
2195 {
2196 invariant_checker(const invariant_checker &);
2197 invariant_checker & operator=(const invariant_checker &);
2198 const stable_vector* p;
2199
2200 public:
2201 invariant_checker(const stable_vector& v):p(&v){}
2202 ~invariant_checker(){BOOST_ASSERT(p->priv_invariant());}
2203 void touch(){}
2204 };
2205 #endif
2206
2207 class ebo_holder
2208 : public node_allocator_type
2209 {
2210 private:
2211 BOOST_MOVABLE_BUT_NOT_COPYABLE(ebo_holder)
2212
2213 public:
2214 template<class AllocatorRLValue>
2215 explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
2216 : node_allocator_type(boost::forward<AllocatorRLValue>(a))
2217 , pool_size(0)
2218 , end_node()
2219 {}
2220
2221 ebo_holder()
2222 : node_allocator_type()
2223 , pool_size(0)
2224 , end_node()
2225 {}
2226
2227 size_type pool_size;
2228 node_base_type end_node;
2229 } internal_data;
2230
2231 node_allocator_type &priv_node_alloc() { return internal_data; }
2232 const node_allocator_type &priv_node_alloc() const { return internal_data; }
2233
2234 index_type index;
2235 #endif
2236 };
2237
2238 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
2239
2240 template <typename InputIterator>
2241 stable_vector(InputIterator, InputIterator) ->
2242 stable_vector<typename iterator_traits<InputIterator>::value_type>;
2243
2244 template <typename InputIterator, typename Allocator>
2245 stable_vector(InputIterator, InputIterator, Allocator const&) ->
2246 stable_vector<typename iterator_traits<InputIterator>::value_type, Allocator>;
2247
2248 #endif
2249
2250 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2251
2252 #undef BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
2253
2254 }
2255
2256
2257
2258 template <class T, class Allocator>
2259 struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> >
2260 {
2261 typedef typename boost::container::stable_vector<T, Allocator>::allocator_type allocator_type;
2262 typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
2263 BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
2264 ::boost::has_trivial_destructor_after_move<pointer>::value;
2265 };
2266
2267 namespace container {
2268
2269 #endif
2270
2271 }}
2272
2273 #include <boost/container/detail/config_end.hpp>
2274
2275 #endif