annotate DEPENDENCIES/generic/include/boost/container/stable_vector.hpp @ 125:34e428693f5d vext

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