stable_vector.hpp 88 KB

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