stable_vector.hpp 85 KB

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