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