stable_vector.hpp 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270
  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/launder.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. inline clear_on_destroy(C &c)
  75. : c_(c), do_clear_(true)
  76. {}
  77. inline void release()
  78. { do_clear_ = false; }
  79. inline ~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. inline explicit node_base(const node_base_ptr_ptr &n)
  109. : up(n)
  110. {}
  111. inline 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. inline explicit node(const typename hook_type::node_base_ptr_ptr &n)
  133. : hook_type(n)
  134. {}
  135. inline 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. inline T &get_data()
  143. { return *boost::move_detail::launder_cast<T*>(&this->m_storage); }
  144. inline const T &get_data() const
  145. { return *boost::move_detail::launder_cast<const T*>(&this->m_storage); }
  146. inline T *get_data_ptr()
  147. { return boost::move_detail::launder_cast<T*>(&this->m_storage); }
  148. inline const T *get_data_ptr() const
  149. { return boost::move_detail::launder_cast<const T*>(&this->m_storage); }
  150. inline ~node()
  151. { boost::move_detail::launder_cast<T*>(&this->m_storage)->~T(); }
  152. #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING)
  153. #pragma GCC diagnostic pop
  154. #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING
  155. # endif
  156. inline 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. BOOST_STATIC_CONSTEXPR 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. inline 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. inline static index_iterator get_fix_up_end(index_type &index)
  201. { return index.end() - (ExtraPointers - 1); }
  202. inline 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. inline explicit stable_vector_iterator(node_base_ptr p) BOOST_NOEXCEPT_OR_NOTHROW
  283. : m_pn(p)
  284. {}
  285. inline stable_vector_iterator() BOOST_NOEXCEPT_OR_NOTHROW
  286. : m_pn() //Value initialization to achieve "null iterators" (N3644)
  287. {}
  288. inline stable_vector_iterator(const stable_vector_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
  289. : m_pn(other.node_pointer())
  290. {}
  291. inline stable_vector_iterator(const nonconst_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
  292. : m_pn(other.node_pointer())
  293. {}
  294. inline 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 inline
  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 inline
  302. reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
  303. { return node_pointer()->get_data(); }
  304. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  305. pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
  306. { return ptr_traits::pointer_to(this->operator*()); }
  307. //Increment / Decrement
  308. inline 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. inline stable_vector_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
  315. { stable_vector_iterator tmp(*this); ++*this; return stable_vector_iterator(tmp); }
  316. inline 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. inline 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 inline
  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. inline 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 inline
  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 inline
  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. inline stable_vector_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
  348. { *this += -off; return *this; }
  349. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  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 inline
  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 inline
  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 inline
  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 inline
  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 inline
  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 inline
  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 inline
  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. inline node_ptr allocate_one()
  476. { return allocator_version_traits_t::allocate_one(this->priv_node_alloc()); }
  477. inline void deallocate_one(const node_ptr &p)
  478. { allocator_version_traits_t::deallocate_one(this->priv_node_alloc(), p); }
  479. inline 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. inline 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. BOOST_STATIC_CONSTEXPR 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. inline 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. inline 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. inline 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. if (BOOST_LIKELY(this != &x)) {
  769. //We know resources can be transferred at comiple time if both allocators are
  770. //always equal or the allocator is going to be propagated
  771. const bool can_steal_resources_alloc
  772. = allocator_traits_type::propagate_on_container_move_assignment::value
  773. || allocator_traits_type::is_always_equal::value;
  774. dtl::bool_<can_steal_resources_alloc> flag;
  775. this->priv_move_assign(boost::move(x), flag);
  776. }
  777. return *this;
  778. }
  779. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  780. //! <b>Effects</b>: Make *this container contains elements from il.
  781. //!
  782. //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
  783. stable_vector& operator=(std::initializer_list<value_type> il)
  784. {
  785. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  786. assign(il.begin(), il.end());
  787. return *this;
  788. }
  789. #endif
  790. //! <b>Effects</b>: Assigns the n copies of val to *this.
  791. //!
  792. //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
  793. //!
  794. //! <b>Complexity</b>: Linear to n.
  795. inline void assign(size_type n, const T& t)
  796. {
  797. typedef constant_iterator<value_type> cvalue_iterator;
  798. this->assign(cvalue_iterator(t, n), cvalue_iterator());
  799. }
  800. //! <b>Effects</b>: Assigns the the range [first, last) to *this.
  801. //!
  802. //! <b>Throws</b>: If memory allocation throws or
  803. //! T's constructor from dereferencing InpIt throws.
  804. //!
  805. //! <b>Complexity</b>: Linear to n.
  806. template<typename InputIterator>
  807. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  808. typename dtl::disable_if_convertible<InputIterator, size_type>::type
  809. #else
  810. void
  811. #endif
  812. assign(InputIterator first,InputIterator last)
  813. {
  814. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  815. iterator first1 = this->begin();
  816. iterator last1 = this->end();
  817. for ( ; first1 != last1 && first != last; ++first1, ++first)
  818. *first1 = *first;
  819. if (first == last){
  820. this->erase(first1, last1);
  821. }
  822. else{
  823. this->insert(last1, first, last);
  824. }
  825. }
  826. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  827. //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this.
  828. //!
  829. //! <b>Throws</b>: If memory allocation throws or
  830. //! T's constructor from dereferencing initializer_list iterator throws.
  831. //!
  832. inline void assign(std::initializer_list<value_type> il)
  833. {
  834. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  835. assign(il.begin(), il.end());
  836. }
  837. #endif
  838. //! <b>Effects</b>: Returns a copy of the internal allocator.
  839. //!
  840. //! <b>Throws</b>: If allocator's copy constructor throws.
  841. //!
  842. //! <b>Complexity</b>: Constant.
  843. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  844. allocator_type get_allocator() const
  845. { return this->priv_node_alloc(); }
  846. //! <b>Effects</b>: Returns a reference to the internal allocator.
  847. //!
  848. //! <b>Throws</b>: Nothing
  849. //!
  850. //! <b>Complexity</b>: Constant.
  851. //!
  852. //! <b>Note</b>: Non-standard extension.
  853. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  854. const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
  855. { return this->priv_node_alloc(); }
  856. //! <b>Effects</b>: Returns a reference to the internal allocator.
  857. //!
  858. //! <b>Throws</b>: Nothing
  859. //!
  860. //! <b>Complexity</b>: Constant.
  861. //!
  862. //! <b>Note</b>: Non-standard extension.
  863. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  864. stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
  865. { return this->priv_node_alloc(); }
  866. //////////////////////////////////////////////
  867. //
  868. // iterators
  869. //
  870. //////////////////////////////////////////////
  871. //! <b>Effects</b>: Returns an iterator to the first element contained in the stable_vector.
  872. //!
  873. //! <b>Throws</b>: Nothing.
  874. //!
  875. //! <b>Complexity</b>: Constant.
  876. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  877. iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
  878. { return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); }
  879. //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
  880. //!
  881. //! <b>Throws</b>: Nothing.
  882. //!
  883. //! <b>Complexity</b>: Constant.
  884. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  885. const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
  886. { return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; }
  887. //! <b>Effects</b>: Returns an iterator to the end of the stable_vector.
  888. //!
  889. //! <b>Throws</b>: Nothing.
  890. //!
  891. //! <b>Complexity</b>: Constant.
  892. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  893. iterator end() BOOST_NOEXCEPT_OR_NOTHROW
  894. { return iterator(this->priv_get_end_node()); }
  895. //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
  896. //!
  897. //! <b>Throws</b>: Nothing.
  898. //!
  899. //! <b>Complexity</b>: Constant.
  900. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  901. const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
  902. { return const_iterator(this->priv_get_end_node()); }
  903. //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
  904. //! of the reversed stable_vector.
  905. //!
  906. //! <b>Throws</b>: Nothing.
  907. //!
  908. //! <b>Complexity</b>: Constant.
  909. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  910. reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
  911. { return reverse_iterator(this->end()); }
  912. //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
  913. //! of the reversed stable_vector.
  914. //!
  915. //! <b>Throws</b>: Nothing.
  916. //!
  917. //! <b>Complexity</b>: Constant.
  918. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  919. const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
  920. { return const_reverse_iterator(this->end()); }
  921. //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
  922. //! of the reversed stable_vector.
  923. //!
  924. //! <b>Throws</b>: Nothing.
  925. //!
  926. //! <b>Complexity</b>: Constant.
  927. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  928. reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
  929. { return reverse_iterator(this->begin()); }
  930. //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
  931. //! of the reversed stable_vector.
  932. //!
  933. //! <b>Throws</b>: Nothing.
  934. //!
  935. //! <b>Complexity</b>: Constant.
  936. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  937. const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
  938. { return const_reverse_iterator(this->begin()); }
  939. //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
  940. //!
  941. //! <b>Throws</b>: Nothing.
  942. //!
  943. //! <b>Complexity</b>: Constant.
  944. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  945. const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
  946. { return this->begin(); }
  947. //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
  948. //!
  949. //! <b>Throws</b>: Nothing.
  950. //!
  951. //! <b>Complexity</b>: Constant.
  952. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  953. const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
  954. { return this->end(); }
  955. //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
  956. //! of the reversed stable_vector.
  957. //!
  958. //! <b>Throws</b>: Nothing.
  959. //!
  960. //! <b>Complexity</b>: Constant.
  961. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  962. const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
  963. { return this->rbegin(); }
  964. //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
  965. //! of the reversed stable_vector.
  966. //!
  967. //! <b>Throws</b>: Nothing.
  968. //!
  969. //! <b>Complexity</b>: Constant.
  970. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  971. const_reverse_iterator crend()const BOOST_NOEXCEPT_OR_NOTHROW
  972. { return this->rend(); }
  973. //////////////////////////////////////////////
  974. //
  975. // capacity
  976. //
  977. //////////////////////////////////////////////
  978. //! <b>Effects</b>: Returns true if the stable_vector contains no elements.
  979. //!
  980. //! <b>Throws</b>: Nothing.
  981. //!
  982. //! <b>Complexity</b>: Constant.
  983. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  984. bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
  985. { return this->index.size() <= ExtraPointers; }
  986. //! <b>Effects</b>: Returns the number of the elements contained in the stable_vector.
  987. //!
  988. //! <b>Throws</b>: Nothing.
  989. //!
  990. //! <b>Complexity</b>: Constant.
  991. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  992. size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
  993. {
  994. const size_type index_size = this->index.size();
  995. return (index_size - ExtraPointers) & (size_type(0u) -size_type(index_size != 0));
  996. }
  997. //! <b>Effects</b>: Returns the largest possible size of the stable_vector.
  998. //!
  999. //! <b>Throws</b>: Nothing.
  1000. //!
  1001. //! <b>Complexity</b>: Constant.
  1002. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1003. size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
  1004. { return this->index.max_size() - ExtraPointers; }
  1005. //! <b>Effects</b>: Inserts or erases elements at the end such that
  1006. //! the size becomes n. New elements are value initialized.
  1007. //!
  1008. //! <b>Throws</b>: If memory allocation throws, or T's value initialization throws.
  1009. //!
  1010. //! <b>Complexity</b>: Linear to the difference between size() and new_size.
  1011. void resize(size_type n)
  1012. {
  1013. typedef value_init_construct_iterator<value_type> value_init_iterator;
  1014. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  1015. if(n > this->size())
  1016. this->insert( this->cend()
  1017. , value_init_iterator(n - this->size()), value_init_iterator());
  1018. else if(n < this->size())
  1019. this->erase(this->cbegin() + difference_type(n), this->cend());
  1020. }
  1021. //! <b>Effects</b>: Inserts or erases elements at the end such that
  1022. //! the size becomes n. New elements are default initialized.
  1023. //!
  1024. //! <b>Throws</b>: If memory allocation throws, or T's default initialization throws.
  1025. //!
  1026. //! <b>Complexity</b>: Linear to the difference between size() and new_size.
  1027. //!
  1028. //! <b>Note</b>: Non-standard extension
  1029. void resize(size_type n, default_init_t)
  1030. {
  1031. typedef default_init_construct_iterator<value_type> default_init_iterator;
  1032. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  1033. if(n > this->size())
  1034. this->insert(this->cend(), default_init_iterator(n - this->size()), default_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 copy constructed from x.
  1040. //!
  1041. //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
  1042. //!
  1043. //! <b>Complexity</b>: Linear to the difference between size() and new_size.
  1044. void resize(size_type n, const T& t)
  1045. {
  1046. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  1047. if(n > this->size())
  1048. this->insert(this->cend(), n - this->size(), t);
  1049. else if(n < this->size())
  1050. this->erase(this->cbegin() + difference_type(n), this->cend());
  1051. }
  1052. //! <b>Effects</b>: Number of elements for which memory has been allocated.
  1053. //! capacity() is always greater than or equal to size().
  1054. //!
  1055. //! <b>Throws</b>: Nothing.
  1056. //!
  1057. //! <b>Complexity</b>: Constant.
  1058. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1059. size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
  1060. {
  1061. const size_type index_size = this->index.size();
  1062. BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
  1063. const size_type node_extra_capacity = this->internal_data.pool_size;
  1064. //Pool count must be less than index capacity, as index is a vector
  1065. BOOST_ASSERT(node_extra_capacity <= (this->index.capacity()- index_size));
  1066. const size_type index_offset =
  1067. (node_extra_capacity - ExtraPointers) & (size_type(0u) - size_type(index_size != 0));
  1068. return index_size + index_offset;
  1069. }
  1070. //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
  1071. //! effect. Otherwise, it is a request for allocation of additional memory.
  1072. //! If the request is successful, then capacity() is greater than or equal to
  1073. //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
  1074. //!
  1075. //! <b>Throws</b>: If memory allocation allocation throws.
  1076. void reserve(size_type n)
  1077. {
  1078. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  1079. if(n > this->max_size()){
  1080. throw_length_error("stable_vector::reserve max_size() exceeded");
  1081. }
  1082. size_type sz = this->size();
  1083. size_type old_capacity = this->capacity();
  1084. if(n > old_capacity){
  1085. index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, n);
  1086. const void * old_ptr = &index[0];
  1087. this->index.reserve(n + ExtraPointers);
  1088. bool realloced = &index[0] != old_ptr;
  1089. //Fix the pointers for the newly allocated buffer
  1090. if(realloced){
  1091. index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
  1092. }
  1093. //Now fill pool if data is not enough
  1094. if((n - sz) > this->internal_data.pool_size){
  1095. this->priv_increase_pool((n - sz) - this->internal_data.pool_size);
  1096. }
  1097. }
  1098. }
  1099. //! <b>Effects</b>: Tries to deallocate the excess of memory created
  1100. //! with previous allocations. The size of the stable_vector is unchanged
  1101. //!
  1102. //! <b>Throws</b>: If memory allocation throws.
  1103. //!
  1104. //! <b>Complexity</b>: Linear to size().
  1105. void shrink_to_fit()
  1106. {
  1107. if(this->capacity()){
  1108. //First empty allocated node pool
  1109. this->priv_clear_pool();
  1110. //If empty completely destroy the index, let's recover default-constructed state
  1111. if(this->empty()){
  1112. this->index.clear();
  1113. this->index.shrink_to_fit();
  1114. this->internal_data.end_node.up = node_base_ptr_ptr();
  1115. }
  1116. //Otherwise, try to shrink-to-fit the index and readjust pointers if necessary
  1117. else{
  1118. const void* old_ptr = &index[0];
  1119. this->index.shrink_to_fit();
  1120. bool realloced = &index[0] != old_ptr;
  1121. //Fix the pointers for the newly allocated buffer
  1122. if(realloced){
  1123. index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
  1124. }
  1125. }
  1126. }
  1127. }
  1128. //////////////////////////////////////////////
  1129. //
  1130. // element access
  1131. //
  1132. //////////////////////////////////////////////
  1133. //! <b>Requires</b>: !empty()
  1134. //!
  1135. //! <b>Effects</b>: Returns a reference to the first
  1136. //! element of the container.
  1137. //!
  1138. //! <b>Throws</b>: Nothing.
  1139. //!
  1140. //! <b>Complexity</b>: Constant.
  1141. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1142. reference front() BOOST_NOEXCEPT_OR_NOTHROW
  1143. {
  1144. BOOST_ASSERT(!this->empty());
  1145. return static_cast<node_reference>(*this->index.front()).get_data();
  1146. }
  1147. //! <b>Requires</b>: !empty()
  1148. //!
  1149. //! <b>Effects</b>: Returns a const reference to the first
  1150. //! element of the container.
  1151. //!
  1152. //! <b>Throws</b>: Nothing.
  1153. //!
  1154. //! <b>Complexity</b>: Constant.
  1155. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1156. const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
  1157. {
  1158. BOOST_ASSERT(!this->empty());
  1159. return static_cast<const_node_reference>(*this->index.front()).get_data();
  1160. }
  1161. //! <b>Requires</b>: !empty()
  1162. //!
  1163. //! <b>Effects</b>: Returns a reference to the last
  1164. //! element of the container.
  1165. //!
  1166. //! <b>Throws</b>: Nothing.
  1167. //!
  1168. //! <b>Complexity</b>: Constant.
  1169. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1170. reference back() BOOST_NOEXCEPT_OR_NOTHROW
  1171. {
  1172. BOOST_ASSERT(!this->empty());
  1173. return static_cast<node_reference>(*this->index[this->size()-1u]).get_data();
  1174. }
  1175. //! <b>Requires</b>: !empty()
  1176. //!
  1177. //! <b>Effects</b>: Returns a const reference to the last
  1178. //! element of the container.
  1179. //!
  1180. //! <b>Throws</b>: Nothing.
  1181. //!
  1182. //! <b>Complexity</b>: Constant.
  1183. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1184. const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
  1185. {
  1186. BOOST_ASSERT(!this->empty());
  1187. return static_cast<const_node_reference>(*this->index[this->size()-1u]).get_data();
  1188. }
  1189. //! <b>Requires</b>: size() > n.
  1190. //!
  1191. //! <b>Effects</b>: Returns a reference to the nth element
  1192. //! from the beginning of the container.
  1193. //!
  1194. //! <b>Throws</b>: Nothing.
  1195. //!
  1196. //! <b>Complexity</b>: Constant.
  1197. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1198. reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
  1199. {
  1200. BOOST_ASSERT(this->size() > n);
  1201. return static_cast<node_reference>(*this->index[n]).get_data();
  1202. }
  1203. //! <b>Requires</b>: size() > n.
  1204. //!
  1205. //! <b>Effects</b>: Returns a const reference to the nth element
  1206. //! from the beginning of the container.
  1207. //!
  1208. //! <b>Throws</b>: Nothing.
  1209. //!
  1210. //! <b>Complexity</b>: Constant.
  1211. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1212. const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
  1213. {
  1214. BOOST_ASSERT(this->size() > n);
  1215. return static_cast<const_node_reference>(*this->index[n]).get_data();
  1216. }
  1217. //! <b>Requires</b>: size() >= n.
  1218. //!
  1219. //! <b>Effects</b>: Returns an iterator to the nth element
  1220. //! from the beginning of the container. Returns end()
  1221. //! if n == size().
  1222. //!
  1223. //! <b>Throws</b>: Nothing.
  1224. //!
  1225. //! <b>Complexity</b>: Constant.
  1226. //!
  1227. //! <b>Note</b>: Non-standard extension
  1228. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1229. iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
  1230. {
  1231. BOOST_ASSERT(this->size() >= n);
  1232. return (this->index.empty()) ? this->end() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
  1233. }
  1234. //! <b>Requires</b>: size() >= n.
  1235. //!
  1236. //! <b>Effects</b>: Returns a const_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 inline
  1246. const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
  1247. {
  1248. BOOST_ASSERT(this->size() >= n);
  1249. return (this->index.empty()) ? this->cend() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
  1250. }
  1251. //! <b>Requires</b>: begin() <= p <= end().
  1252. //!
  1253. //! <b>Effects</b>: Returns the index of the element pointed by p
  1254. //! and size() if p == end().
  1255. //!
  1256. //! <b>Throws</b>: Nothing.
  1257. //!
  1258. //! <b>Complexity</b>: Constant.
  1259. //!
  1260. //! <b>Note</b>: Non-standard extension
  1261. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1262. size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
  1263. { return this->priv_index_of(p.node_pointer()); }
  1264. //! <b>Requires</b>: begin() <= p <= end().
  1265. //!
  1266. //! <b>Effects</b>: Returns the index of the element pointed by p
  1267. //! and size() if p == end().
  1268. //!
  1269. //! <b>Throws</b>: Nothing.
  1270. //!
  1271. //! <b>Complexity</b>: Constant.
  1272. //!
  1273. //! <b>Note</b>: Non-standard extension
  1274. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1275. size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
  1276. { return this->priv_index_of(p.node_pointer()); }
  1277. //! <b>Requires</b>: size() > n.
  1278. //!
  1279. //! <b>Effects</b>: Returns a reference to the nth element
  1280. //! from the beginning of the container.
  1281. //!
  1282. //! <b>Throws</b>: range_error if n >= size()
  1283. //!
  1284. //! <b>Complexity</b>: Constant.
  1285. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1286. reference at(size_type n)
  1287. {
  1288. if(n >= this->size()){
  1289. throw_out_of_range("vector::at invalid subscript");
  1290. }
  1291. return operator[](n);
  1292. }
  1293. //! <b>Requires</b>: size() > n.
  1294. //!
  1295. //! <b>Effects</b>: Returns a const reference to the nth element
  1296. //! from the beginning of the container.
  1297. //!
  1298. //! <b>Throws</b>: range_error if n >= size()
  1299. //!
  1300. //! <b>Complexity</b>: Constant.
  1301. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1302. const_reference at(size_type n)const
  1303. {
  1304. if(n >= this->size()){
  1305. throw_out_of_range("vector::at invalid subscript");
  1306. }
  1307. return operator[](n);
  1308. }
  1309. //////////////////////////////////////////////
  1310. //
  1311. // modifiers
  1312. //
  1313. //////////////////////////////////////////////
  1314. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1315. //! <b>Effects</b>: Inserts an object of type T constructed with
  1316. //! std::forward<Args>(args)... in the end of the stable_vector.
  1317. //!
  1318. //! <b>Returns</b>: A reference to the created object.
  1319. //!
  1320. //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
  1321. //!
  1322. //! <b>Complexity</b>: Amortized constant time.
  1323. template<class ...Args>
  1324. reference emplace_back(Args &&...args)
  1325. {
  1326. typedef emplace_functor<Args...> EmplaceFunctor;
  1327. typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;
  1328. EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
  1329. return *this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
  1330. }
  1331. //! <b>Requires</b>: p must be a valid iterator of *this.
  1332. //!
  1333. //! <b>Effects</b>: Inserts an object of type T constructed with
  1334. //! std::forward<Args>(args)... before p
  1335. //!
  1336. //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
  1337. //!
  1338. //! <b>Complexity</b>: If p is end(), amortized constant time
  1339. //! Linear time otherwise.
  1340. template<class ...Args>
  1341. iterator emplace(const_iterator p, Args && ...args)
  1342. {
  1343. BOOST_ASSERT(this->priv_in_range_or_end(p));
  1344. difference_type pos_n = p - cbegin();
  1345. typedef emplace_functor<Args...> EmplaceFunctor;
  1346. typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;
  1347. EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
  1348. this->insert(p, EmplaceIterator(ef), EmplaceIterator());
  1349. return iterator(this->begin() + pos_n);
  1350. }
  1351. #else
  1352. #define BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE(N) \
  1353. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  1354. reference emplace_back(BOOST_MOVE_UREF##N)\
  1355. {\
  1356. typedef emplace_functor##N\
  1357. BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\
  1358. typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;\
  1359. EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\
  1360. return *this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator());\
  1361. }\
  1362. \
  1363. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  1364. iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  1365. {\
  1366. BOOST_ASSERT(this->priv_in_range_or_end(p));\
  1367. typedef emplace_functor##N\
  1368. BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\
  1369. typedef emplace_iterator<value_type, EmplaceFunctor> EmplaceIterator;\
  1370. EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\
  1371. const size_type pos_n = size_type(p - this->cbegin());\
  1372. this->insert(p, EmplaceIterator(ef), EmplaceIterator());\
  1373. return this->begin() += difference_type(pos_n);\
  1374. }\
  1375. //
  1376. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE)
  1377. #undef BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE
  1378. #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  1379. #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1380. //! <b>Effects</b>: Inserts a copy of x at the end of the stable_vector.
  1381. //!
  1382. //! <b>Throws</b>: If memory allocation throws or
  1383. //! T's copy constructor throws.
  1384. //!
  1385. //! <b>Complexity</b>: Amortized constant time.
  1386. void push_back(const T &x);
  1387. //! <b>Effects</b>: Constructs a new element in the end of the stable_vector
  1388. //! and moves the resources of x to this new element.
  1389. //!
  1390. //! <b>Throws</b>: If memory allocation throws.
  1391. //!
  1392. //! <b>Complexity</b>: Amortized constant time.
  1393. void push_back(T &&x);
  1394. #else
  1395. BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
  1396. #endif
  1397. #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1398. //! <b>Requires</b>: p must be a valid iterator of *this.
  1399. //!
  1400. //! <b>Effects</b>: Insert a copy of x before p.
  1401. //!
  1402. //! <b>Returns</b>: An iterator to the inserted element.
  1403. //!
  1404. //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
  1405. //!
  1406. //! <b>Complexity</b>: If p is end(), amortized constant time
  1407. //! Linear time otherwise.
  1408. iterator insert(const_iterator p, const T &x);
  1409. //! <b>Requires</b>: p must be a valid iterator of *this.
  1410. //!
  1411. //! <b>Effects</b>: Insert a new element before p with x's resources.
  1412. //!
  1413. //! <b>Returns</b>: an iterator to the inserted element.
  1414. //!
  1415. //! <b>Throws</b>: If memory allocation throws.
  1416. //!
  1417. //! <b>Complexity</b>: If p is end(), amortized constant time
  1418. //! Linear time otherwise.
  1419. iterator insert(const_iterator p, T &&x);
  1420. #else
  1421. BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
  1422. #endif
  1423. //! <b>Requires</b>: p must be a valid iterator of *this.
  1424. //!
  1425. //! <b>Effects</b>: Insert n copies of x before p.
  1426. //!
  1427. //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
  1428. //!
  1429. //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
  1430. //!
  1431. //! <b>Complexity</b>: Linear to n.
  1432. iterator insert(const_iterator p, size_type n, const T& t)
  1433. {
  1434. BOOST_ASSERT(this->priv_in_range_or_end(p));
  1435. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  1436. typedef constant_iterator<value_type> cvalue_iterator;
  1437. return this->insert(p, cvalue_iterator(t, n), cvalue_iterator());
  1438. }
  1439. //! <b>Requires</b>: p must be a valid iterator of *this.
  1440. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  1441. //! <b>Requires</b>: p must be a valid iterator of *this.
  1442. //!
  1443. //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before p.
  1444. //!
  1445. //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
  1446. //!
  1447. //! <b>Complexity</b>: Linear to distance [il.begin(), il.end()).
  1448. inline iterator insert(const_iterator p, std::initializer_list<value_type> il)
  1449. {
  1450. //Position checks done by insert()
  1451. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  1452. return insert(p, il.begin(), il.end());
  1453. }
  1454. #endif
  1455. //! <b>Requires</b>: pos must be a valid iterator of *this.
  1456. //!
  1457. //! <b>Effects</b>: Insert a copy of the [first, last) range before p.
  1458. //!
  1459. //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
  1460. //!
  1461. //! <b>Throws</b>: If memory allocation throws, T's constructor from a
  1462. //! dereferenced InpIt throws or T's copy constructor throws.
  1463. //!
  1464. //! <b>Complexity</b>: Linear to distance [first, last).
  1465. template <class InputIterator>
  1466. iterator insert(const_iterator p, InputIterator first, InputIterator last
  1467. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1468. //Put this as argument instead of the return type as old GCC's like 3.4
  1469. //detect this and the next disable_if_or as overloads
  1470. , typename dtl::disable_if_or
  1471. < void
  1472. , dtl::is_convertible<InputIterator, size_type>
  1473. , dtl::is_not_input_iterator<InputIterator>
  1474. >::type* = 0
  1475. #endif
  1476. )
  1477. {
  1478. BOOST_ASSERT(this->priv_in_range_or_end(p));
  1479. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  1480. const difference_type pos_n = p - this->cbegin();
  1481. for(; first != last; ++first){
  1482. this->emplace(p, *first);
  1483. }
  1484. return this->begin() + difference_type(pos_n);
  1485. }
  1486. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1487. template <class FwdIt>
  1488. typename dtl::disable_if_or
  1489. < iterator
  1490. , dtl::is_convertible<FwdIt, size_type>
  1491. , dtl::is_input_iterator<FwdIt>
  1492. >::type
  1493. insert(const_iterator p, FwdIt first, FwdIt last)
  1494. {
  1495. BOOST_ASSERT(this->priv_in_range_or_end(p));
  1496. const size_type num_new = boost::container::iterator_udistance(first, last);
  1497. const size_type idx = static_cast<size_type>(p - this->cbegin());
  1498. if(num_new){
  1499. //Fills the node pool and inserts num_new null pointers in idx.
  1500. //If a new buffer was needed fixes up pointers up to idx so
  1501. //past-new nodes are not aligned until the end of this function
  1502. //or in a rollback in case of exception
  1503. index_iterator it_past_newly_constructed(this->priv_insert_forward_non_templated(idx, num_new));
  1504. const index_iterator it_past_new(it_past_newly_constructed + difference_type(num_new));
  1505. {
  1506. //Prepare rollback
  1507. insert_rollback rollback(*this, it_past_newly_constructed, it_past_new);
  1508. while(first != last){
  1509. const node_ptr n = this->priv_get_from_pool();
  1510. BOOST_ASSERT(!!n);
  1511. //Put it in the index so rollback can return it in pool if construct_in_place throws
  1512. *it_past_newly_constructed = n;
  1513. //Constructs and fixes up pointers This can throw
  1514. this->priv_build_node_from_it(n, it_past_newly_constructed, first);
  1515. ++first;
  1516. ++it_past_newly_constructed;
  1517. }
  1518. //rollback.~insert_rollback() called in case of exception
  1519. }
  1520. //Fix up pointers for past-new nodes (new nodes were fixed during construction) and
  1521. //nodes before insertion p in priv_insert_forward_non_templated(...)
  1522. index_traits_type::fix_up_pointers_from(this->index, it_past_newly_constructed);
  1523. }
  1524. return this->begin() + static_cast<difference_type>(idx);
  1525. }
  1526. #endif
  1527. //! <b>Effects</b>: Removes the last element from the stable_vector.
  1528. //!
  1529. //! <b>Throws</b>: Nothing.
  1530. //!
  1531. //! <b>Complexity</b>: Constant time.
  1532. inline void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
  1533. {
  1534. BOOST_ASSERT(!this->empty());
  1535. this->erase(--this->cend());
  1536. }
  1537. //! <b>Effects</b>: Erases the element at p.
  1538. //!
  1539. //! <b>Throws</b>: Nothing.
  1540. //!
  1541. //! <b>Complexity</b>: Linear to the elements between p and the
  1542. //! last element. Constant if p is the last element.
  1543. inline iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
  1544. {
  1545. BOOST_ASSERT(this->priv_in_range(p));
  1546. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  1547. const difference_type d = p - this->cbegin();
  1548. index_iterator it = this->index.begin() + d;
  1549. this->priv_delete_node(p.node_pointer());
  1550. it = this->index.erase(it);
  1551. index_traits_type::fix_up_pointers_from(this->index, it);
  1552. return iterator(node_ptr_traits::static_cast_from(*it));
  1553. }
  1554. //! <b>Effects</b>: Erases the elements pointed by [first, last).
  1555. //!
  1556. //! <b>Throws</b>: Nothing.
  1557. //!
  1558. //! <b>Complexity</b>: Linear to the distance between first and last
  1559. //! plus linear to the elements between p and the last element.
  1560. iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
  1561. {
  1562. BOOST_ASSERT(first == last ||
  1563. (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last)));
  1564. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  1565. const const_iterator cbeg(this->cbegin());
  1566. const size_type d1 = static_cast<size_type>(first - cbeg),
  1567. d2 = static_cast<size_type>(last - cbeg);
  1568. size_type d_dif = d2 - d1;
  1569. if(d_dif){
  1570. multiallocation_chain holder;
  1571. const index_iterator it1(this->index.begin() + difference_type(d1));
  1572. const index_iterator it2(it1 + difference_type(d_dif));
  1573. index_iterator it(it1);
  1574. while(d_dif){
  1575. --d_dif;
  1576. node_base_ptr &nb = *it;
  1577. ++it;
  1578. node_type &n = *node_ptr_traits::static_cast_from(nb);
  1579. this->priv_destroy_node(n);
  1580. holder.push_back(node_ptr_traits::pointer_to(n));
  1581. }
  1582. this->priv_put_in_pool(holder);
  1583. const index_iterator e = this->index.erase(it1, it2);
  1584. index_traits_type::fix_up_pointers_from(this->index, e);
  1585. }
  1586. return iterator(last.node_pointer());
  1587. }
  1588. //! <b>Effects</b>: Swaps the contents of *this and x.
  1589. //!
  1590. //! <b>Throws</b>: Nothing.
  1591. //!
  1592. //! <b>Complexity</b>: Constant.
  1593. void swap(stable_vector & x)
  1594. BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
  1595. || allocator_traits_type::is_always_equal::value)
  1596. {
  1597. BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value ||
  1598. allocator_traits_type::is_always_equal::value ||
  1599. this->get_stored_allocator() == x.get_stored_allocator());
  1600. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT;
  1601. dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
  1602. dtl::swap_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
  1603. //vector's allocator is swapped here
  1604. this->index.swap(x.index);
  1605. this->priv_swap_members(x);
  1606. }
  1607. //! <b>Effects</b>: Erases all the elements of the stable_vector.
  1608. //!
  1609. //! <b>Throws</b>: Nothing.
  1610. //!
  1611. //! <b>Complexity</b>: Linear to the number of elements in the stable_vector.
  1612. inline void clear() BOOST_NOEXCEPT_OR_NOTHROW
  1613. { this->erase(this->cbegin(),this->cend()); }
  1614. //! <b>Effects</b>: Returns true if x and y are equal
  1615. //!
  1616. //! <b>Complexity</b>: Linear to the number of elements in the container.
  1617. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1618. friend bool operator==(const stable_vector& x, const stable_vector& y)
  1619. { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
  1620. //! <b>Effects</b>: Returns true if x and y are unequal
  1621. //!
  1622. //! <b>Complexity</b>: Linear to the number of elements in the container.
  1623. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1624. friend bool operator!=(const stable_vector& x, const stable_vector& y)
  1625. { return !(x == y); }
  1626. //! <b>Effects</b>: Returns true if x is less than y
  1627. //!
  1628. //! <b>Complexity</b>: Linear to the number of elements in the container.
  1629. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1630. friend bool operator<(const stable_vector& x, const stable_vector& y)
  1631. { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
  1632. //! <b>Effects</b>: Returns true if x is greater than y
  1633. //!
  1634. //! <b>Complexity</b>: Linear to the number of elements in the container.
  1635. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1636. friend bool operator>(const stable_vector& x, const stable_vector& y)
  1637. { return y < x; }
  1638. //! <b>Effects</b>: Returns true if x is equal or less than y
  1639. //!
  1640. //! <b>Complexity</b>: Linear to the number of elements in the container.
  1641. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1642. friend bool operator<=(const stable_vector& x, const stable_vector& y)
  1643. { return !(y < x); }
  1644. //! <b>Effects</b>: Returns true if x is equal or greater than y
  1645. //!
  1646. //! <b>Complexity</b>: Linear to the number of elements in the container.
  1647. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1648. friend bool operator>=(const stable_vector& x, const stable_vector& y)
  1649. { return !(x < y); }
  1650. //! <b>Effects</b>: x.swap(y)
  1651. //!
  1652. //! <b>Complexity</b>: Constant.
  1653. inline friend void swap(stable_vector& x, stable_vector& y)
  1654. BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
  1655. { x.swap(y); }
  1656. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  1657. private:
  1658. void priv_move_assign(BOOST_RV_REF(stable_vector) x, dtl::bool_<true> /*steal_resources*/)
  1659. {
  1660. //Resources can be transferred if both allocators are
  1661. //going to be equal after this function (either propagated or already equal)
  1662. BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
  1663. //Destroy objects but retain memory in case x reuses it in the future
  1664. this->clear();
  1665. //Move allocator if needed
  1666. dtl::bool_<allocator_traits_type::
  1667. propagate_on_container_move_assignment::value> flag;
  1668. dtl::move_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
  1669. //Take resources
  1670. this->index = boost::move(x.index); //this also moves the vector's allocator if needed
  1671. this->priv_swap_members(x);
  1672. }
  1673. void priv_move_assign(BOOST_RV_REF(stable_vector) x, dtl::bool_<false> /*steal_resources*/)
  1674. {
  1675. //We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
  1676. //Resources can be transferred if both allocators are equal
  1677. if (this->priv_node_alloc() == x.priv_node_alloc()) {
  1678. this->priv_move_assign(boost::move(x), dtl::true_());
  1679. }
  1680. else {
  1681. this->assign(boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
  1682. }
  1683. }
  1684. bool priv_in_range(const_iterator pos) const
  1685. {
  1686. return (this->begin() <= pos) && (pos < this->end());
  1687. }
  1688. inline bool priv_in_range_or_end(const_iterator pos) const
  1689. {
  1690. return (this->begin() <= pos) && (pos <= this->end());
  1691. }
  1692. inline size_type priv_index_of(node_ptr p) const
  1693. {
  1694. //Check range
  1695. BOOST_ASSERT(this->index.empty() || (this->index.data() <= p->up));
  1696. BOOST_ASSERT(this->index.empty() || p->up <= (this->index.data() + this->index.size()));
  1697. return this->index.empty() ? 0u : size_type(p->up - this->index.data());
  1698. }
  1699. class insert_rollback
  1700. {
  1701. public:
  1702. insert_rollback(stable_vector &sv, index_iterator &it_past_constructed, const index_iterator &it_past_new)
  1703. : m_sv(sv), m_it_past_constructed(it_past_constructed), m_it_past_new(it_past_new)
  1704. {}
  1705. ~insert_rollback()
  1706. {
  1707. if(m_it_past_constructed != m_it_past_new){
  1708. m_sv.priv_put_in_pool(node_ptr_traits::static_cast_from(*m_it_past_constructed));
  1709. index_iterator e = m_sv.index.erase(m_it_past_constructed, m_it_past_new);
  1710. index_traits_type::fix_up_pointers_from(m_sv.index, e);
  1711. }
  1712. }
  1713. private:
  1714. stable_vector &m_sv;
  1715. index_iterator &m_it_past_constructed;
  1716. const index_iterator &m_it_past_new;
  1717. };
  1718. class push_back_rollback
  1719. {
  1720. public:
  1721. inline push_back_rollback(stable_vector &sv, const node_ptr &p)
  1722. : m_sv(sv), m_p(p)
  1723. {}
  1724. inline ~push_back_rollback()
  1725. {
  1726. if(m_p){
  1727. m_sv.priv_put_in_pool(m_p);
  1728. }
  1729. }
  1730. inline void release()
  1731. { m_p = node_ptr(); }
  1732. private:
  1733. stable_vector &m_sv;
  1734. node_ptr m_p;
  1735. };
  1736. index_iterator priv_insert_forward_non_templated(size_type idx, size_type num_new)
  1737. {
  1738. index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, num_new);
  1739. //Now try to fill the pool with new data
  1740. if(this->internal_data.pool_size < num_new){
  1741. this->priv_increase_pool(num_new - this->internal_data.pool_size);
  1742. }
  1743. //Now try to make room in the vector
  1744. const node_base_ptr_ptr old_buffer = this->index.data();
  1745. this->index.insert(this->index.begin() + (difference_type)idx, num_new, node_ptr());
  1746. bool new_buffer = this->index.data() != old_buffer;
  1747. //Fix the pointers for the newly allocated buffer
  1748. const index_iterator index_beg = this->index.begin();
  1749. if(new_buffer){
  1750. index_traits_type::fix_up_pointers(index_beg, index_beg + (difference_type)idx);
  1751. }
  1752. return index_beg + (difference_type)idx;
  1753. }
  1754. inline bool priv_capacity_bigger_than_size() const
  1755. {
  1756. return this->index.capacity() > this->index.size() &&
  1757. this->internal_data.pool_size > 0;
  1758. }
  1759. template <class U>
  1760. void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
  1761. {
  1762. if(BOOST_LIKELY(this->priv_capacity_bigger_than_size())){
  1763. //Enough memory in the pool and in the index
  1764. const node_ptr p = this->priv_get_from_pool();
  1765. BOOST_ASSERT(!!p);
  1766. {
  1767. push_back_rollback rollback(*this, p);
  1768. //This might throw
  1769. this->priv_build_node_from_convertible(p, ::boost::forward<U>(x));
  1770. rollback.release();
  1771. }
  1772. //This can't throw as there is room for a new elements in the index
  1773. index_iterator new_index = this->index.insert(this->index.end() - ExtraPointers, p);
  1774. index_traits_type::fix_up_pointers_from(this->index, new_index);
  1775. }
  1776. else{
  1777. this->insert(this->cend(), ::boost::forward<U>(x));
  1778. }
  1779. }
  1780. iterator priv_insert(const_iterator p, const value_type &t)
  1781. {
  1782. BOOST_ASSERT(this->priv_in_range_or_end(p));
  1783. typedef constant_iterator<value_type> cvalue_iterator;
  1784. return this->insert(p, cvalue_iterator(t, 1), cvalue_iterator());
  1785. }
  1786. iterator priv_insert(const_iterator p, BOOST_RV_REF(T) x)
  1787. {
  1788. BOOST_ASSERT(this->priv_in_range_or_end(p));
  1789. typedef repeat_iterator<T> repeat_it;
  1790. typedef boost::move_iterator<repeat_it> repeat_move_it;
  1791. //Just call more general insert(p, size, value) and return iterator
  1792. return this->insert(p, repeat_move_it(repeat_it(x, 1)), repeat_move_it(repeat_it()));
  1793. }
  1794. void priv_clear_pool()
  1795. {
  1796. if(!this->index.empty() && this->index.back()){
  1797. node_base_ptr &pool_first_ref = *(this->index.end() - 2);
  1798. node_base_ptr &pool_last_ref = this->index.back();
  1799. multiallocation_chain holder;
  1800. holder.incorporate_after( holder.before_begin()
  1801. , node_ptr_traits::static_cast_from(pool_first_ref)
  1802. , node_ptr_traits::static_cast_from(pool_last_ref)
  1803. , internal_data.pool_size);
  1804. this->deallocate_individual(holder);
  1805. pool_first_ref = pool_last_ref = 0;
  1806. this->internal_data.pool_size = 0;
  1807. }
  1808. }
  1809. void priv_increase_pool(size_type n)
  1810. {
  1811. node_base_ptr &pool_first_ref = *(this->index.end() - 2);
  1812. node_base_ptr &pool_last_ref = this->index.back();
  1813. multiallocation_chain holder;
  1814. holder.incorporate_after( holder.before_begin()
  1815. , node_ptr_traits::static_cast_from(pool_first_ref)
  1816. , node_ptr_traits::static_cast_from(pool_last_ref)
  1817. , internal_data.pool_size);
  1818. multiallocation_chain m;
  1819. this->allocate_individual(n, m);
  1820. holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
  1821. this->internal_data.pool_size += n;
  1822. typename multiallocation_chain::pointer_pair data(holder.extract_data());
  1823. pool_first_ref = data.first;
  1824. pool_last_ref = data.second;
  1825. }
  1826. void priv_put_in_pool(const node_ptr &p)
  1827. {
  1828. node_base_ptr &pool_first_ref = *(this->index.end()-2);
  1829. node_base_ptr &pool_last_ref = this->index.back();
  1830. multiallocation_chain holder;
  1831. holder.incorporate_after( holder.before_begin()
  1832. , node_ptr_traits::static_cast_from(pool_first_ref)
  1833. , node_ptr_traits::static_cast_from(pool_last_ref)
  1834. , internal_data.pool_size);
  1835. holder.push_front(p);
  1836. ++this->internal_data.pool_size;
  1837. typename multiallocation_chain::pointer_pair ret(holder.extract_data());
  1838. pool_first_ref = ret.first;
  1839. pool_last_ref = ret.second;
  1840. }
  1841. void priv_put_in_pool(multiallocation_chain &ch)
  1842. {
  1843. node_base_ptr &pool_first_ref = *(this->index.end()-(ExtraPointers-1));
  1844. node_base_ptr &pool_last_ref = this->index.back();
  1845. ch.incorporate_after( ch.before_begin()
  1846. , node_ptr_traits::static_cast_from(pool_first_ref)
  1847. , node_ptr_traits::static_cast_from(pool_last_ref)
  1848. , internal_data.pool_size);
  1849. this->internal_data.pool_size = ch.size();
  1850. const typename multiallocation_chain::pointer_pair ret(ch.extract_data());
  1851. pool_first_ref = ret.first;
  1852. pool_last_ref = ret.second;
  1853. }
  1854. node_ptr priv_get_from_pool()
  1855. {
  1856. //Precondition: index is not empty
  1857. BOOST_ASSERT(!this->index.empty());
  1858. node_base_ptr &pool_first_ref = *(this->index.end() - (ExtraPointers-1));
  1859. node_base_ptr &pool_last_ref = this->index.back();
  1860. multiallocation_chain holder;
  1861. holder.incorporate_after( holder.before_begin()
  1862. , node_ptr_traits::static_cast_from(pool_first_ref)
  1863. , node_ptr_traits::static_cast_from(pool_last_ref)
  1864. , internal_data.pool_size);
  1865. node_ptr ret = holder.pop_front();
  1866. --this->internal_data.pool_size;
  1867. if(!internal_data.pool_size){
  1868. pool_first_ref = pool_last_ref = node_ptr();
  1869. }
  1870. else{
  1871. const typename multiallocation_chain::pointer_pair data(holder.extract_data());
  1872. pool_first_ref = data.first;
  1873. pool_last_ref = data.second;
  1874. }
  1875. return ret;
  1876. }
  1877. inline node_base_ptr priv_get_end_node() const
  1878. { return node_base_ptr_traits::pointer_to(const_cast<node_base_type&>(this->internal_data.end_node)); }
  1879. inline void priv_destroy_node(const node_type &n)
  1880. {
  1881. allocator_traits<node_allocator_type>::
  1882. destroy(this->priv_node_alloc(), &n);
  1883. }
  1884. inline void priv_delete_node(const node_ptr &n)
  1885. {
  1886. this->priv_destroy_node(*n);
  1887. this->priv_put_in_pool(n);
  1888. }
  1889. template<class Iterator>
  1890. void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it)
  1891. {
  1892. node_type *praw = ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
  1893. node_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
  1894. BOOST_CONTAINER_TRY{
  1895. //This can throw
  1896. boost::container::construct_in_place
  1897. ( this->priv_node_alloc()
  1898. , praw->get_data_ptr()
  1899. , it);
  1900. }
  1901. BOOST_CONTAINER_CATCH(...) {
  1902. praw->destroy_header();
  1903. this->priv_node_alloc().deallocate(p, 1);
  1904. BOOST_CONTAINER_RETHROW
  1905. }
  1906. BOOST_CONTAINER_CATCH_END
  1907. }
  1908. template<class ValueConvertible>
  1909. void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible)
  1910. {
  1911. node_type *praw = ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) node_type;
  1912. BOOST_CONTAINER_TRY{
  1913. //This can throw
  1914. boost::container::allocator_traits<node_allocator_type>::construct
  1915. ( this->priv_node_alloc()
  1916. , p->get_data_ptr()
  1917. , ::boost::forward<ValueConvertible>(value_convertible));
  1918. }
  1919. BOOST_CONTAINER_CATCH(...) {
  1920. praw->destroy_header();
  1921. this->priv_node_alloc().deallocate(p, 1);
  1922. BOOST_CONTAINER_RETHROW
  1923. }
  1924. BOOST_CONTAINER_CATCH_END
  1925. }
  1926. void priv_swap_members(stable_vector &x)
  1927. {
  1928. boost::adl_move_swap(this->internal_data.pool_size, x.internal_data.pool_size);
  1929. index_traits_type::readjust_end_node(this->index, this->internal_data.end_node);
  1930. index_traits_type::readjust_end_node(x.index, x.internal_data.end_node);
  1931. }
  1932. #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
  1933. bool priv_invariant()const
  1934. {
  1935. index_type & index_ref = const_cast<index_type&>(this->index);
  1936. const size_type index_size = this->index.size();
  1937. if(!index_size)
  1938. return !this->capacity() && !this->size();
  1939. if(index_size < ExtraPointers)
  1940. return false;
  1941. const size_type bucket_extra_capacity = this->index.capacity()- index_size;
  1942. const size_type node_extra_capacity = this->internal_data.pool_size;
  1943. if(bucket_extra_capacity < node_extra_capacity){
  1944. return false;
  1945. }
  1946. if(this->priv_get_end_node() != *(index.end() - ExtraPointers)){
  1947. return false;
  1948. }
  1949. if(!index_traits_type::invariants(index_ref)){
  1950. return false;
  1951. }
  1952. size_type n = this->capacity() - this->size();
  1953. node_base_ptr &pool_first_ref = *(index_ref.end() - (ExtraPointers-1));
  1954. node_base_ptr &pool_last_ref = index_ref.back();
  1955. multiallocation_chain holder;
  1956. holder.incorporate_after( holder.before_begin()
  1957. , node_ptr_traits::static_cast_from(pool_first_ref)
  1958. , node_ptr_traits::static_cast_from(pool_last_ref)
  1959. , internal_data.pool_size);
  1960. typename multiallocation_chain::iterator beg(holder.begin()), end(holder.end());
  1961. size_type num_pool = 0;
  1962. while(beg != end){
  1963. ++num_pool;
  1964. ++beg;
  1965. }
  1966. return n >= num_pool && num_pool == internal_data.pool_size;
  1967. }
  1968. class invariant_checker
  1969. {
  1970. invariant_checker(const invariant_checker &);
  1971. invariant_checker & operator=(const invariant_checker &);
  1972. const stable_vector* p;
  1973. public:
  1974. invariant_checker(const stable_vector& v):p(&v){}
  1975. ~invariant_checker(){BOOST_ASSERT(p->priv_invariant());}
  1976. void touch(){}
  1977. };
  1978. #endif
  1979. class ebo_holder
  1980. : public node_allocator_type
  1981. {
  1982. private:
  1983. BOOST_MOVABLE_BUT_NOT_COPYABLE(ebo_holder)
  1984. public:
  1985. template<class AllocatorRLValue>
  1986. explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
  1987. : node_allocator_type(boost::forward<AllocatorRLValue>(a))
  1988. , pool_size(0)
  1989. , end_node()
  1990. {}
  1991. ebo_holder()
  1992. : node_allocator_type()
  1993. , pool_size(0)
  1994. , end_node()
  1995. {}
  1996. size_type pool_size;
  1997. node_base_type end_node;
  1998. } internal_data;
  1999. node_allocator_type &priv_node_alloc() { return internal_data; }
  2000. const node_allocator_type &priv_node_alloc() const { return internal_data; }
  2001. index_type index;
  2002. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  2003. };
  2004. #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
  2005. template <typename InputIterator>
  2006. stable_vector(InputIterator, InputIterator) ->
  2007. stable_vector<typename iterator_traits<InputIterator>::value_type>;
  2008. template <typename InputIterator, typename Allocator>
  2009. stable_vector(InputIterator, InputIterator, Allocator const&) ->
  2010. stable_vector<typename iterator_traits<InputIterator>::value_type, Allocator>;
  2011. #endif
  2012. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  2013. #undef BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
  2014. } //namespace container {
  2015. //!has_trivial_destructor_after_move<> == true_type
  2016. //!specialization for optimizations
  2017. template <class T, class Allocator>
  2018. struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> >
  2019. {
  2020. typedef typename boost::container::stable_vector<T, Allocator>::allocator_type allocator_type;
  2021. typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
  2022. BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
  2023. ::boost::has_trivial_destructor_after_move<pointer>::value;
  2024. };
  2025. namespace container {
  2026. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  2027. }} //namespace boost{ namespace container {
  2028. #include <boost/container/detail/config_end.hpp>
  2029. #endif //BOOST_CONTAINER_STABLE_VECTOR_HPP