devector.hpp 107 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Benedek Thaler 2015-2016
  4. // (C) Copyright Ion Gaztanaga 2019-2020. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // See http://www.boost.org/libs/container for documentation.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11. #ifndef BOOST_CONTAINER_DEVECTOR_HPP
  12. #define BOOST_CONTAINER_DEVECTOR_HPP
  13. #include <boost/container/detail/config_begin.hpp>
  14. #include <boost/container/detail/workaround.hpp>
  15. #include <cstring> // memcpy
  16. #include <boost/assert.hpp>
  17. #include <boost/container/detail/copy_move_algo.hpp>
  18. #include <boost/container/new_allocator.hpp> //new_allocator
  19. #include <boost/container/allocator_traits.hpp> //allocator_traits
  20. #include <boost/container/detail/algorithm.hpp> //equal()
  21. #include <boost/container/throw_exception.hpp>
  22. #include <boost/container/options.hpp>
  23. #include <boost/container/detail/guards_dended.hpp>
  24. #include <boost/container/detail/iterator.hpp>
  25. #include <boost/container/detail/iterators.hpp>
  26. #include <boost/container/detail/destroyers.hpp>
  27. #include <boost/container/detail/min_max.hpp>
  28. #include <boost/container/detail/next_capacity.hpp>
  29. #include <boost/container/detail/alloc_helpers.hpp>
  30. #include <boost/container/detail/advanced_insert_int.hpp>
  31. // move
  32. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  33. #include <boost/move/detail/fwd_macros.hpp>
  34. #endif
  35. #include <boost/move/detail/move_helpers.hpp>
  36. #include <boost/move/adl_move_swap.hpp>
  37. #include <boost/move/iterator.hpp>
  38. #include <boost/move/traits.hpp>
  39. #include <boost/move/utility_core.hpp>
  40. #include <boost/move/detail/to_raw_pointer.hpp>
  41. #include <boost/move/algo/detail/merge.hpp>
  42. #include <boost/move/detail/force_ptr.hpp>
  43. //std
  44. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  45. #include <initializer_list> //for std::initializer_list
  46. #endif
  47. namespace boost {
  48. namespace container {
  49. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  50. struct growth_factor_60;
  51. template<class Options, class AllocatorSizeType>
  52. struct get_devector_opt
  53. {
  54. typedef devector_opt< typename default_if_void<typename Options::growth_factor_type, growth_factor_60>::type
  55. , typename default_if_void<typename Options::stored_size_type, AllocatorSizeType>::type
  56. , default_if_zero<Options::free_fraction, relocate_on_90::value>::value
  57. > type;
  58. };
  59. template<class AllocatorSizeType>
  60. struct get_devector_opt<void, AllocatorSizeType>
  61. {
  62. typedef devector_opt< growth_factor_60, AllocatorSizeType, relocate_on_90::value> type;
  63. };
  64. #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  65. struct reserve_only_tag_t {};
  66. struct reserve_uninitialized_t {};
  67. struct review_implementation_t {};
  68. //struct unsafe_uninitialized_tag_t {};
  69. /**
  70. * A vector-like sequence container providing front and back operations
  71. * (e.g: `push_front`/`pop_front`/`push_back`/`pop_back`) with amortized constant complexity.
  72. *
  73. * Models the [SequenceContainer], [ReversibleContainer], and [AllocatorAwareContainer] concepts.
  74. *
  75. * **Requires**:
  76. * - `T` shall be [MoveInsertable] into the devector.
  77. * - `T` shall be [Erasable] from any `devector<T, allocator_type, GP>`.
  78. * - `GrowthFactor`, and `Allocator` must model the concepts with the same names or be void.
  79. *
  80. * **Definition**: `T` is `NothrowConstructible` if it's either nothrow move constructible or
  81. * nothrow copy constructible.
  82. *
  83. * **Definition**: `T` is `NothrowAssignable` if it's either nothrow move assignable or
  84. * nothrow copy assignable.
  85. *
  86. * **Exceptions**: The exception specifications assume `T` is nothrow [Destructible].
  87. *
  88. * Most methods providing the strong exception guarantee assume `T` either has a move
  89. * constructor marked noexcept or is [CopyInsertable] into the devector. If it isn't true,
  90. * and the move constructor throws, the guarantee is waived and the effects are unspecified.
  91. *
  92. * In addition to the exceptions specified in the **Throws** clause, the following operations
  93. * of `T` can throw when any of the specified concept is required:
  94. * - [DefaultInsertable][]: Default constructor
  95. * - [MoveInsertable][]: Move constructor
  96. * - [CopyInsertable][]: Copy constructor
  97. * - [DefaultConstructible][]: Default constructor
  98. * - [EmplaceConstructible][]: Constructor selected by the given arguments
  99. * - [MoveAssignable][]: Move assignment operator
  100. * - [CopyAssignable][]: Copy assignment operator
  101. *
  102. * Furthermore, not `noexcept` methods throws whatever the allocator throws
  103. * if memory allocation fails. Such methods also throw `length_error` if the capacity
  104. * exceeds `max_size()`.
  105. *
  106. * **Remark**: If a method invalidates some iterators, it also invalidates references
  107. * and pointers to the elements pointed by the invalidated iterators.
  108. *
  109. *! \tparam Options A type produced from \c boost::container::devector_options.
  110. *
  111. * [SequenceContainer]: http://en.cppreference.com/w/cpp/concept/SequenceContainer
  112. * [ReversibleContainer]: http://en.cppreference.com/w/cpp/concept/ReversibleContainer
  113. * [AllocatorAwareContainer]: http://en.cppreference.com/w/cpp/concept/AllocatorAwareContainer
  114. * [DefaultInsertable]: http://en.cppreference.com/w/cpp/concept/DefaultInsertable
  115. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  116. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  117. * [Erasable]: http://en.cppreference.com/w/cpp/concept/Erasable
  118. * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
  119. * [Destructible]: http://en.cppreference.com/w/cpp/concept/Destructible
  120. * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
  121. * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
  122. * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
  123. */
  124. template < typename T, class A BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void)>
  125. class devector
  126. {
  127. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  128. typedef boost::container::allocator_traits
  129. <typename real_allocator<T, A>::type> allocator_traits_type;
  130. typedef typename allocator_traits_type::size_type alloc_size_type;
  131. typedef typename get_devector_opt<Options, alloc_size_type>::type options_type;
  132. typedef typename options_type::growth_factor_type growth_factor_type;
  133. typedef typename options_type::stored_size_type stored_size_type;
  134. static const std::size_t devector_min_free_fraction =
  135. options_type::free_fraction;
  136. #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  137. public:
  138. // Standard Interface Types:
  139. typedef T value_type;
  140. typedef BOOST_CONTAINER_IMPDEF
  141. (typename real_allocator<T BOOST_MOVE_I A>::type) allocator_type;
  142. typedef allocator_type stored_allocator_type;
  143. typedef typename allocator_traits<allocator_type>::pointer pointer;
  144. typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
  145. typedef typename allocator_traits<allocator_type>::reference reference;
  146. typedef typename allocator_traits<allocator_type>::const_reference const_reference;
  147. typedef typename allocator_traits<allocator_type>::size_type size_type;
  148. typedef typename allocator_traits<allocator_type>::difference_type difference_type;
  149. typedef pointer iterator;
  150. typedef const_pointer const_iterator;
  151. typedef BOOST_CONTAINER_IMPDEF
  152. (boost::container::reverse_iterator<iterator>) reverse_iterator;
  153. typedef BOOST_CONTAINER_IMPDEF
  154. (boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
  155. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  156. private:
  157. BOOST_COPYABLE_AND_MOVABLE(devector)
  158. // Guard to deallocate buffer on exception
  159. typedef typename detail::allocation_guard<allocator_type> allocation_guard;
  160. // Random access pseudo iterator always yielding to the same result
  161. typedef constant_iterator<T> cvalue_iterator;
  162. static size_type to_internal_capacity(size_type desired_capacity)
  163. {
  164. const size_type rounder = devector_min_free_fraction - 2u;
  165. const size_type divisor = devector_min_free_fraction - 1u;
  166. size_type const nc = ((desired_capacity + rounder) / divisor) * devector_min_free_fraction;
  167. BOOST_ASSERT(desired_capacity <= (nc - nc / devector_min_free_fraction));
  168. return nc;
  169. }
  170. #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  171. // Standard Interface
  172. public:
  173. // construct/copy/destroy
  174. /**
  175. * **Effects**: Constructs an empty devector.
  176. *
  177. * **Postcondition**: `empty() && front_free_capacity() == 0
  178. * && back_free_capacity() == 0`.
  179. *
  180. * **Complexity**: Constant.
  181. */
  182. devector() BOOST_NOEXCEPT
  183. : m_()
  184. {}
  185. /**
  186. * **Effects**: Constructs an empty devector, using the specified allocator.
  187. *
  188. * **Postcondition**: `empty() && front_free_capacity() == 0
  189. * && back_free_capacity() == 0`.
  190. *
  191. * **Complexity**: Constant.
  192. */
  193. explicit devector(const allocator_type& allocator) BOOST_NOEXCEPT
  194. : m_(allocator)
  195. {}
  196. /**
  197. * **Effects**: Constructs an empty devector, using the specified allocator
  198. * and reserves `n` slots as if `reserve(n)` was called.
  199. *
  200. * **Postcondition**: `empty() && capacity() >= n`.
  201. *
  202. * **Exceptions**: Strong exception guarantee.
  203. *
  204. * **Complexity**: Constant.
  205. */
  206. devector(size_type n, reserve_only_tag_t, const allocator_type& allocator = allocator_type())
  207. : m_(reserve_only_tag_t(), allocator, to_internal_capacity(n))
  208. {}
  209. /**
  210. * **Effects**: Constructs an empty devector, using the specified allocator
  211. * and reserves at least `front_free_cap + back_free_cap` slots as if `reserve_front(front_cap)` and
  212. * `reserve_back(back_cap)` was called.
  213. *
  214. * **Postcondition**: `empty() && front_free_capacity() >= front_free_cap
  215. * && back_free_capacity() >= back_free_cap`.
  216. *
  217. * **Exceptions**: Strong exception guarantee.
  218. *
  219. * **Complexity**: Constant.
  220. */
  221. devector(size_type front_free_cap, size_type back_free_cap, reserve_only_tag_t, const allocator_type& allocator = allocator_type())
  222. : m_(reserve_only_tag_t(), allocator, front_free_cap, back_free_cap)
  223. {}
  224. /**
  225. * [DefaultInsertable]: http://en.cppreference.com/w/cpp/concept/DefaultInsertable
  226. *
  227. * **Effects**: Constructs a devector with `n` value_initialized elements using the specified allocator.
  228. *
  229. * **Requires**: `T` shall be [DefaultInsertable] into `*this`.
  230. *
  231. * **Postcondition**: `size() == n`.
  232. *
  233. * **Exceptions**: Strong exception guarantee.
  234. *
  235. * **Complexity**: Linear in `n`.
  236. */
  237. explicit devector(size_type n, const allocator_type& allocator = allocator_type())
  238. : m_(reserve_uninitialized_t(), allocator, n)
  239. {
  240. allocation_guard buffer_guard(m_.buffer, m_.capacity, get_allocator_ref());
  241. boost::container::uninitialized_value_init_alloc_n(get_allocator_ref(), n, this->priv_raw_begin());
  242. buffer_guard.release();
  243. BOOST_ASSERT(invariants_ok());
  244. }
  245. /**
  246. * **Effects**: Constructs a devector with `n` default-initialized elements using the specified allocator.
  247. *
  248. * **Requires**: `T` shall be [DefaultInsertable] into `*this`.
  249. *
  250. * **Postcondition**: `size() == n`.
  251. *
  252. * **Exceptions**: Strong exception guarantee.
  253. *
  254. * **Complexity**: Linear in `n`.
  255. */
  256. explicit devector(size_type n, default_init_t, const allocator_type& allocator = allocator_type())
  257. : m_(reserve_uninitialized_t(), allocator, n)
  258. {
  259. allocation_guard buffer_guard(m_.buffer, m_.capacity, get_allocator_ref());
  260. boost::container::uninitialized_default_init_alloc_n(get_allocator_ref(), n, this->priv_raw_begin());
  261. buffer_guard.release();
  262. BOOST_ASSERT(invariants_ok());
  263. }
  264. /**
  265. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  266. *
  267. * **Effects**: Constructs a devector with `n` copies of `value`, using the specified allocator.
  268. *
  269. * **Requires**: `T` shall be [CopyInsertable] into `*this`.
  270. *
  271. * **Postcondition**: `size() == n`.
  272. *
  273. * **Exceptions**: Strong exception guarantee.
  274. *
  275. * **Complexity**: Linear in `n`.
  276. */
  277. devector(size_type n, const T& value, const allocator_type& allocator = allocator_type())
  278. : m_(reserve_uninitialized_t(), allocator, n)
  279. {
  280. construct_from_range(cvalue_iterator(value, n), cvalue_iterator());
  281. BOOST_ASSERT(invariants_ok());
  282. }
  283. /**
  284. * **Effects**: Constructs a devector equal to the range `[first,last)`, using the specified allocator.
  285. *
  286. * **Requires**: `T` shall be [EmplaceConstructible] into `*this` from `*first`. If the specified
  287. * iterator does not meet the forward iterator requirements, `T` shall also be [MoveInsertable]
  288. * into `*this`.
  289. *
  290. * **Postcondition**: `size() == boost::container::iterator_distance(first, last)
  291. *
  292. * **Exceptions**: Strong exception guarantee.
  293. *
  294. * **Complexity**: Makes only `N` calls to the copy constructor of `T` (where `N` is the distance between `first`
  295. * and `last`), at most one allocation and no reallocations if iterators first and last are of forward,
  296. * bidirectional, or random access categories. It makes `O(N)` calls to the copy constructor of `T`
  297. * and `O(log(N)) reallocations if they are just input iterators.
  298. *
  299. * **Remarks**: Each iterator in the range `[first,last)` shall be dereferenced exactly once,
  300. * unless an exception is thrown.
  301. *
  302. * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
  303. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  304. */
  305. template <class InputIterator>
  306. devector(InputIterator first, InputIterator last, const allocator_type& allocator = allocator_type()
  307. //Input iterators
  308. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
  309. < void
  310. BOOST_MOVE_I dtl::is_convertible<InputIterator BOOST_MOVE_I size_type>
  311. BOOST_MOVE_I dtl::is_not_input_iterator<InputIterator>
  312. >::type * = 0)
  313. )
  314. : m_(allocator)
  315. {
  316. BOOST_CONTAINER_TRY{
  317. while (first != last) {
  318. this->emplace_back(*first++);
  319. }
  320. BOOST_ASSERT(invariants_ok());
  321. }
  322. BOOST_CONTAINER_CATCH(...){
  323. this->destroy_elements(m_.buffer + m_.front_idx, m_.buffer + m_.back_idx);
  324. this->deallocate_buffer();
  325. }
  326. BOOST_CONTAINER_CATCH_END
  327. }
  328. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  329. template <class ForwardIterator>
  330. devector(ForwardIterator first, ForwardIterator last, const allocator_type& allocator = allocator_type()
  331. //Other iterators
  332. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
  333. < void
  334. BOOST_MOVE_I dtl::is_convertible<ForwardIterator BOOST_MOVE_I size_type>
  335. BOOST_MOVE_I dtl::is_input_iterator<ForwardIterator>
  336. >::type * = 0)
  337. )
  338. : m_(reserve_uninitialized_t(), allocator, boost::container::iterator_udistance(first, last))
  339. {
  340. this->construct_from_range(first, last);
  341. BOOST_ASSERT(invariants_ok());
  342. }
  343. #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  344. /**
  345. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  346. *
  347. * **Effects**: Copy constructs a devector.
  348. *
  349. * **Requires**: `T` shall be [CopyInsertable] into `*this`.
  350. *
  351. * **Postcondition**: `this->size() == x.size()`.
  352. *
  353. * **Exceptions**: Strong exception guarantee.
  354. *
  355. * **Complexity**: Linear in the size of `x`.
  356. */
  357. devector(const devector& x)
  358. : m_(reserve_uninitialized_t(), allocator_traits_type::select_on_container_copy_construction(x.get_allocator_ref()), x.size())
  359. {
  360. this->construct_from_range(x.begin(), x.end());
  361. BOOST_ASSERT(invariants_ok());
  362. }
  363. /**
  364. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  365. *
  366. * **Effects**: Copy constructs a devector, using the specified allocator.
  367. *
  368. * **Requires**: `T` shall be [CopyInsertable] into `*this`.
  369. *
  370. * **Postcondition**: `*this == x`.
  371. *
  372. * **Exceptions**: Strong exception guarantee.
  373. *
  374. * **Complexity**: Linear in the size of `x`.
  375. */
  376. devector(const devector& x, const allocator_type& allocator)
  377. : m_(reserve_uninitialized_t(), allocator, x.size())
  378. {
  379. this->construct_from_range(x.begin(), x.end());
  380. BOOST_ASSERT(invariants_ok());
  381. }
  382. /**
  383. * **Effects**: Moves `rhs`'s resources to `*this`.
  384. *
  385. * **Throws**: Nothing.
  386. *
  387. * **Postcondition**: *this has the same value `rhs` had before the operation.
  388. * `rhs` is left in an unspecified but valid state.
  389. *
  390. * **Exceptions**: Strong exception guarantee if not `noexcept`.
  391. *
  392. * **Complexity**: Constant.
  393. */
  394. devector(BOOST_RV_REF(devector) rhs) BOOST_NOEXCEPT_OR_NOTHROW
  395. : m_(::boost::move(rhs.m_))
  396. {
  397. BOOST_ASSERT( invariants_ok());
  398. BOOST_ASSERT(rhs.invariants_ok());
  399. }
  400. /**
  401. * **Effects**: Moves `rhs`'s resources to `*this`, using the specified allocator.
  402. *
  403. * **Throws**: If allocation or T's move constructor throws.
  404. *
  405. * **Postcondition**: *this has the same value `rhs` had before the operation.
  406. * `rhs` is left in an unspecified but valid state.
  407. *
  408. * **Exceptions**: Strong exception guarantee if not `noexcept`.
  409. *
  410. * **Complexity**: Linear if allocator != rhs.get_allocator(), otherwise constant.
  411. */
  412. devector(BOOST_RV_REF(devector) rhs, const allocator_type& allocator)
  413. : m_(review_implementation_t(), allocator, rhs.m_.buffer, rhs.m_.front_idx, rhs.m_.back_idx, rhs.m_.capacity)
  414. {
  415. // TODO should move elems-by-elems if the two allocators differ
  416. // buffer is already acquired, reset rhs
  417. rhs.m_.capacity = 0u;
  418. rhs.m_.buffer = pointer();
  419. rhs.m_.front_idx = 0;
  420. rhs.m_.back_idx = 0;
  421. BOOST_ASSERT( invariants_ok());
  422. BOOST_ASSERT(rhs.invariants_ok());
  423. }
  424. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  425. /**
  426. * **Equivalent to**: `devector(il.begin(), il.end(), allocator)`.
  427. */
  428. devector(const std::initializer_list<T>& il, const allocator_type& allocator = allocator_type())
  429. : m_(reserve_uninitialized_t(), allocator, il.size())
  430. {
  431. this->construct_from_range(il.begin(), il.end());
  432. BOOST_ASSERT(invariants_ok());
  433. }
  434. #endif
  435. /**
  436. * **Effects**: Destroys the devector. All stored values are destroyed and
  437. * used memory, if any, deallocated.
  438. *
  439. * **Complexity**: Linear in the size of `*this`.
  440. */
  441. ~devector() BOOST_NOEXCEPT
  442. {
  443. destroy_elements(m_.buffer + m_.front_idx, m_.buffer + m_.back_idx);
  444. deallocate_buffer();
  445. }
  446. /**
  447. * **Effects**: Copies elements of `x` to `*this`. Previously
  448. * held elements get copy assigned to or destroyed.
  449. *
  450. * **Requires**: `T` shall be [CopyInsertable] into `*this`.
  451. *
  452. * **Postcondition**: `this->size() == x.size()`, the elements of
  453. * `*this` are copies of elements in `x` in the same order.
  454. *
  455. * **Returns**: `*this`.
  456. *
  457. * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
  458. * and the allocator is allowed to be propagated
  459. * ([propagate_on_container_copy_assignment] is true),
  460. * Basic exception guarantee otherwise.
  461. *
  462. * **Complexity**: Linear in the size of `x` and `*this`.
  463. *
  464. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  465. * [propagate_on_container_copy_assignment]: http://en.cppreference.com/w/cpp/memory/allocator_traits
  466. */
  467. BOOST_CONTAINER_FORCEINLINE devector& operator=(BOOST_COPY_ASSIGN_REF(devector) rhs)
  468. {
  469. const devector &x = rhs;
  470. if (this == &x) { return *this; } // skip self
  471. BOOST_IF_CONSTEXPR(allocator_traits_type::propagate_on_container_copy_assignment::value)
  472. {
  473. allocator_type &this_alloc = this->get_allocator_ref();
  474. const allocator_type &other_alloc = x.get_allocator_ref();
  475. if (this_alloc != other_alloc)
  476. {
  477. // new allocator cannot free existing storage
  478. this->clear();
  479. this->deallocate_buffer();
  480. m_.capacity = 0u;
  481. m_.buffer = pointer();
  482. }
  483. this_alloc = other_alloc;
  484. }
  485. size_type n = x.size();
  486. if (m_.capacity >= n)
  487. {
  488. this->overwrite_buffer(x.begin(), x.end());
  489. }
  490. else
  491. {
  492. this->allocate_and_copy_range(x.begin(), x.end());
  493. }
  494. BOOST_ASSERT(invariants_ok());
  495. return *this;
  496. }
  497. /**
  498. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  499. *
  500. * **Effects**: Moves elements of `x` to `*this`. Previously
  501. * held elements get move/copy assigned to or destroyed.
  502. *
  503. * **Requires**: `T` shall be [MoveInsertable] into `*this`.
  504. *
  505. * **Postcondition**: `x` is left in an unspecified but valid state.
  506. *
  507. * **Returns**: `*this`.
  508. *
  509. * **Exceptions**: Basic exception guarantee if not `noexcept`.
  510. *
  511. * **Complexity**: Constant if allocator_traits_type::
  512. * propagate_on_container_move_assignment is true or
  513. * this->get>allocator() == x.get_allocator(). Linear otherwise.
  514. */
  515. devector& operator=(BOOST_RV_REF(devector) x)
  516. BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
  517. || allocator_traits_type::is_always_equal::value)
  518. {
  519. BOOST_CONSTEXPR_OR_CONST bool copy_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
  520. BOOST_IF_CONSTEXPR (copy_alloc || get_allocator_ref() == x.get_allocator_ref())
  521. {
  522. this->clear();
  523. this->deallocate_buffer();
  524. if (copy_alloc)
  525. {
  526. this->get_allocator_ref() = boost::move(x.get_allocator_ref());
  527. }
  528. m_.capacity = x.m_.capacity;
  529. m_.buffer = x.m_.buffer;
  530. m_.front_idx = x.m_.front_idx;
  531. m_.back_idx = x.m_.back_idx;
  532. // leave x in valid state
  533. x.m_.capacity = 0u;
  534. x.m_.buffer = pointer();
  535. x.m_.back_idx = x.m_.front_idx = 0;
  536. }
  537. else
  538. {
  539. // if the allocator shouldn't be copied and they do not compare equal
  540. // we can't steal memory.
  541. move_iterator<iterator> xbegin = boost::make_move_iterator(x.begin());
  542. move_iterator<iterator> xend = boost::make_move_iterator(x.end());
  543. if (copy_alloc)
  544. {
  545. get_allocator_ref() = boost::move(x.get_allocator_ref());
  546. }
  547. if (m_.capacity >= x.size())
  548. {
  549. overwrite_buffer(xbegin, xend);
  550. }
  551. else
  552. {
  553. allocate_and_copy_range(xbegin, xend);
  554. }
  555. }
  556. BOOST_ASSERT(invariants_ok());
  557. return *this;
  558. }
  559. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  560. /**
  561. * **Effects**: Copies elements of `il` to `*this`. Previously
  562. * held elements get copy assigned to or destroyed.
  563. *
  564. * **Requires**: `T` shall be [CopyInsertable] into `*this` and [CopyAssignable].
  565. *
  566. * **Postcondition**: `this->size() == il.size()`, the elements of
  567. * `*this` are copies of elements in `il` in the same order.
  568. *
  569. * **Exceptions**: Strong exception guarantee if `T` is nothrow copy assignable
  570. * from `T` and `NothrowConstructible`, Basic exception guarantee otherwise.
  571. *
  572. * **Returns**: `*this`.
  573. *
  574. * **Complexity**: Linear in the size of `il` and `*this`.
  575. *
  576. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  577. * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
  578. */
  579. BOOST_CONTAINER_FORCEINLINE devector& operator=(std::initializer_list<T> il)
  580. {
  581. this->assign(il.begin(), il.end());
  582. return *this;
  583. }
  584. #endif
  585. /**
  586. * **Effects**: Replaces elements of `*this` with a copy of `[first,last)`.
  587. * Previously held elements get copy assigned to or destroyed.
  588. *
  589. * **Requires**: `T` shall be [EmplaceConstructible] from `*first`. If the specified iterator
  590. * does not meet the forward iterator requirements, `T` shall be also [MoveInsertable] into `*this`.
  591. *
  592. * **Precondition**: `first` and `last` are not iterators into `*this`.
  593. *
  594. * **Postcondition**: `size() == N`, where `N` is the distance between `first` and `last`.
  595. *
  596. * **Exceptions**: Strong exception guarantee if `T` is nothrow copy assignable
  597. * from `*first` and `NothrowConstructible`, Basic exception guarantee otherwise.
  598. *
  599. * **Complexity**: Linear in the distance between `first` and `last`.
  600. * Makes a single reallocation at most if the iterators `first` and `last`
  601. * are of forward, bidirectional, or random access categories. It makes
  602. * `O(log(N))` reallocations if they are just input iterators.
  603. *
  604. * **Remarks**: Each iterator in the range `[first,last)` shall be dereferenced exactly once,
  605. * unless an exception is thrown.
  606. *
  607. * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
  608. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  609. */
  610. template <class InputIterator>
  611. void assign(InputIterator first, InputIterator last
  612. //Input iterators
  613. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
  614. < void
  615. BOOST_MOVE_I dtl::is_convertible<InputIterator BOOST_MOVE_I size_type>
  616. BOOST_MOVE_I dtl::is_not_input_iterator<InputIterator>
  617. >::type * = 0)
  618. )
  619. {
  620. first = overwrite_buffer_impl(first, last, dtl::false_());
  621. while (first != last)
  622. {
  623. this->emplace_back(*first++);
  624. }
  625. }
  626. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  627. template <class ForwardIterator>
  628. void assign(ForwardIterator first, ForwardIterator last
  629. //Other iterators
  630. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
  631. < void
  632. BOOST_MOVE_I dtl::is_convertible<ForwardIterator BOOST_MOVE_I size_type>
  633. BOOST_MOVE_I dtl::is_input_iterator<ForwardIterator>
  634. >::type * = 0)
  635. )
  636. {
  637. const size_type n = boost::container::iterator_udistance(first, last);
  638. if (m_.capacity >= n)
  639. {
  640. overwrite_buffer(first, last);
  641. }
  642. else
  643. {
  644. allocate_and_copy_range(first, last);
  645. }
  646. BOOST_ASSERT(invariants_ok());
  647. }
  648. #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  649. /**
  650. * **Effects**: Replaces elements of `*this` with `n` copies of `u`.
  651. * Previously held elements get copy assigned to or destroyed.
  652. *
  653. * **Requires**: `T` shall be [CopyInsertable] into `*this` and
  654. * [CopyAssignable].
  655. *
  656. * **Precondition**: `u` is not a reference into `*this`.
  657. *
  658. * **Postcondition**: `size() == n` and the elements of
  659. * `*this` are copies of `u`.
  660. *
  661. * **Exceptions**: Strong exception guarantee if `T` is nothrow copy assignable
  662. * from `u` and `NothrowConstructible`, Basic exception guarantee otherwise.
  663. *
  664. * **Complexity**: Linear in `n` and the size of `*this`.
  665. *
  666. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  667. * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
  668. */
  669. BOOST_CONTAINER_FORCEINLINE void assign(size_type n, const T& u)
  670. {
  671. cvalue_iterator first(u, n);
  672. cvalue_iterator last;
  673. this->assign(first, last);
  674. }
  675. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  676. /** **Equivalent to**: `assign(il.begin(), il.end())`. */
  677. BOOST_CONTAINER_FORCEINLINE void assign(std::initializer_list<T> il)
  678. {
  679. this->assign(il.begin(), il.end());
  680. }
  681. #endif
  682. /**
  683. * **Returns**: A copy of the allocator associated with the container.
  684. *
  685. * **Complexity**: Constant.
  686. */
  687. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  688. allocator_type get_allocator() const BOOST_NOEXCEPT
  689. {
  690. return static_cast<const allocator_type&>(m_);
  691. }
  692. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  693. const allocator_type &get_stored_allocator() const BOOST_NOEXCEPT
  694. {
  695. return static_cast<const allocator_type&>(m_);
  696. }
  697. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  698. allocator_type &get_stored_allocator() BOOST_NOEXCEPT
  699. {
  700. return static_cast<allocator_type&>(m_);
  701. }
  702. // iterators
  703. /**
  704. * **Returns**: A iterator pointing to the first element in the devector,
  705. * or the past the end iterator if the devector is empty.
  706. *
  707. * **Complexity**: Constant.
  708. */
  709. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  710. iterator begin() BOOST_NOEXCEPT
  711. {
  712. return m_.buffer + m_.front_idx;
  713. }
  714. /**
  715. * **Returns**: A constant iterator pointing to the first element in the devector,
  716. * or the past the end iterator if the devector is empty.
  717. *
  718. * **Complexity**: Constant.
  719. */
  720. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  721. const_iterator begin() const BOOST_NOEXCEPT
  722. {
  723. return m_.buffer + m_.front_idx;
  724. }
  725. /**
  726. * **Returns**: An iterator pointing past the last element of the container.
  727. *
  728. * **Complexity**: Constant.
  729. */
  730. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  731. iterator end() BOOST_NOEXCEPT
  732. {
  733. return m_.buffer + m_.back_idx;
  734. }
  735. /**
  736. * **Returns**: A constant iterator pointing past the last element of the container.
  737. *
  738. * **Complexity**: Constant.
  739. */
  740. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  741. const_iterator end() const BOOST_NOEXCEPT
  742. {
  743. return m_.buffer + m_.back_idx;
  744. }
  745. /**
  746. * **Returns**: A reverse iterator pointing to the first element in the reversed devector,
  747. * or the reverse past the end iterator if the devector is empty.
  748. *
  749. * **Complexity**: Constant.
  750. */
  751. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  752. reverse_iterator rbegin() BOOST_NOEXCEPT
  753. {
  754. return reverse_iterator(m_.buffer + m_.back_idx);
  755. }
  756. /**
  757. * **Returns**: A constant reverse iterator
  758. * pointing to the first element in the reversed devector,
  759. * or the reverse past the end iterator if the devector is empty.
  760. *
  761. * **Complexity**: Constant.
  762. */
  763. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  764. const_reverse_iterator rbegin() const BOOST_NOEXCEPT
  765. {
  766. return const_reverse_iterator(m_.buffer + m_.back_idx);
  767. }
  768. /**
  769. * **Returns**: A reverse iterator pointing past the last element in the
  770. * reversed container, or to the beginning of the reversed container if it's empty.
  771. *
  772. * **Complexity**: Constant.
  773. */
  774. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  775. reverse_iterator rend() BOOST_NOEXCEPT
  776. {
  777. return reverse_iterator(m_.buffer + m_.front_idx);
  778. }
  779. /**
  780. * **Returns**: A constant reverse iterator pointing past the last element in the
  781. * reversed container, or to the beginning of the reversed container if it's empty.
  782. *
  783. * **Complexity**: Constant.
  784. */
  785. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  786. const_reverse_iterator rend() const BOOST_NOEXCEPT
  787. {
  788. return const_reverse_iterator(m_.buffer + m_.front_idx);
  789. }
  790. /**
  791. * **Returns**: A constant iterator pointing to the first element in the devector,
  792. * or the past the end iterator if the devector is empty.
  793. *
  794. * **Complexity**: Constant.
  795. */
  796. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  797. const_iterator cbegin() const BOOST_NOEXCEPT
  798. {
  799. return m_.buffer + m_.front_idx;
  800. }
  801. /**
  802. * **Returns**: A constant iterator pointing past the last element of the container.
  803. *
  804. * **Complexity**: Constant.
  805. */
  806. const_iterator cend() const BOOST_NOEXCEPT
  807. {
  808. return m_.buffer + m_.back_idx;
  809. }
  810. /**
  811. * **Returns**: A constant reverse iterator
  812. * pointing to the first element in the reversed devector,
  813. * or the reverse past the end iterator if the devector is empty.
  814. *
  815. * **Complexity**: Constant.
  816. */
  817. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  818. const_reverse_iterator crbegin() const BOOST_NOEXCEPT
  819. {
  820. return const_reverse_iterator(m_.buffer + m_.back_idx);
  821. }
  822. /**
  823. * **Returns**: A constant reverse iterator pointing past the last element in the
  824. * reversed container, or to the beginning of the reversed container if it's empty.
  825. *
  826. * **Complexity**: Constant.
  827. */
  828. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  829. const_reverse_iterator crend() const BOOST_NOEXCEPT
  830. {
  831. return const_reverse_iterator(m_.buffer + m_.front_idx);
  832. }
  833. // capacity
  834. /**
  835. * **Returns**: True, if `size() == 0`, false otherwise.
  836. *
  837. * **Complexity**: Constant.
  838. */
  839. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  840. bool empty() const BOOST_NOEXCEPT
  841. {
  842. return m_.front_idx == m_.back_idx;
  843. }
  844. /**
  845. * **Returns**: The number of elements the devector contains.
  846. *
  847. * **Complexity**: Constant.
  848. */
  849. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  850. size_type size() const BOOST_NOEXCEPT
  851. {
  852. return size_type(m_.back_idx - m_.front_idx);
  853. }
  854. /**
  855. * **Returns**: The maximum number of elements the devector could possibly hold.
  856. *
  857. * **Complexity**: Constant.
  858. */
  859. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  860. size_type max_size() const BOOST_NOEXCEPT
  861. {
  862. size_type alloc_max = allocator_traits_type::max_size(get_allocator_ref());
  863. size_type size_type_max = (size_type)-1;
  864. return (alloc_max <= size_type_max) ? size_type(alloc_max) : size_type_max;
  865. }
  866. /**
  867. * **Returns**: The *minimum* number of elements that can be inserted into devector using
  868. * position-based insertions without requiring a reallocation. Note that, unlike in
  869. * typical sequence containers like `vector`, `capacity()`, `capacity()` can be smaller than `size()`.
  870. * This can happen if a user inserts elements in a particular way (usually inserting at
  871. * front up to front_free_capacity() and at back up to back_free_capacity()).
  872. *
  873. * **Complexity**: Constant.
  874. */
  875. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  876. size_type capacity() const BOOST_NOEXCEPT
  877. {
  878. size_type const cap_reserve = m_.capacity/devector_min_free_fraction;
  879. return m_.capacity > cap_reserve ? (m_.capacity - cap_reserve) : 0u;
  880. }
  881. /**
  882. * **Returns**: The total number of elements that can be pushed to the front of the
  883. * devector without requiring reallocation.
  884. *
  885. * **Complexity**: Constant.
  886. */
  887. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  888. size_type front_free_capacity() const BOOST_NOEXCEPT
  889. {
  890. return m_.front_idx;
  891. }
  892. /**
  893. * **Returns**: The total number of elements that can be pushed to the back of the
  894. * devector without requiring reallocation.
  895. *
  896. * **Complexity**: Constant.
  897. */
  898. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  899. size_type back_free_capacity() const BOOST_NOEXCEPT
  900. {
  901. return size_type(m_.capacity - m_.back_idx);
  902. }
  903. /**
  904. * **Effects**: If `sz` is greater than the size of `*this`,
  905. * additional value-initialized elements are inserted. Invalidates iterators
  906. * if reallocation is needed. If `sz` is smaller than than the size of `*this`,
  907. * elements are erased from the extremes.
  908. *
  909. * **Requires**: T shall be [MoveInsertable] into *this and [DefaultConstructible].
  910. *
  911. * **Postcondition**: `sz == size()`.
  912. *
  913. * **Exceptions**: Strong exception guarantee.
  914. *
  915. * **Complexity**: Linear in the size of `*this` and `sz`.
  916. *
  917. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  918. * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
  919. */
  920. BOOST_CONTAINER_FORCEINLINE void resize(size_type sz)
  921. {
  922. this->resize_back(sz);
  923. }
  924. /**
  925. * **Effects**: Same as resize(sz) but creates default-initialized
  926. * value-initialized.
  927. */
  928. BOOST_CONTAINER_FORCEINLINE void resize(size_type sz, default_init_t)
  929. {
  930. this->resize_back(sz, default_init);
  931. }
  932. /**
  933. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  934. *
  935. * **Effects**: If `sz` is greater than the size of `*this`,
  936. * copies of `c` are inserted at extremes.
  937. * If `sz` is smaller than than the size of `*this`,
  938. * elements are popped from the extremes.
  939. *
  940. * **Postcondition**: `sz == size()`.
  941. *
  942. * **Requires**: `T` shall be [CopyInsertable] into `*this`.
  943. *
  944. * **Exceptions**: Strong exception guarantee.
  945. *
  946. * **Complexity**: Linear in the size of `*this` and `sz`.
  947. */
  948. BOOST_CONTAINER_FORCEINLINE void resize(size_type sz, const T& c)
  949. {
  950. this->resize_back(sz, c);
  951. }
  952. /**
  953. * **Effects**: If `sz` is greater than the size of `*this`,
  954. * additional value-initialized elements are inserted
  955. * to the front. Invalidates iterators if reallocation is needed.
  956. * If `sz` is smaller than than the size of `*this`,
  957. * elements are popped from the front.
  958. *
  959. * **Requires**: T shall be [MoveInsertable] into *this and [DefaultConstructible].
  960. *
  961. * **Postcondition**: `sz == size()`.
  962. *
  963. * **Exceptions**: Strong exception guarantee.
  964. *
  965. * **Complexity**: Linear in the size of `*this` and `sz`.
  966. *
  967. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  968. * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
  969. */
  970. BOOST_CONTAINER_FORCEINLINE void resize_front(size_type sz)
  971. {
  972. resize_front_impl(sz);
  973. BOOST_ASSERT(invariants_ok());
  974. }
  975. /**
  976. * **Effects**: If `sz` is greater than the size of `*this`,
  977. * additional value-initialized elements are inserted
  978. * to the front. Invalidates iterators if reallocation is needed.
  979. * If `sz` is smaller than than the size of `*this`,
  980. * elements are popped from the front.
  981. *
  982. * **Requires**: T shall be [MoveInsertable] into *this and default_initializable.
  983. *
  984. * **Postcondition**: `sz == size()`.
  985. *
  986. * **Exceptions**: Strong exception guarantee.
  987. *
  988. * **Complexity**: Linear in the size of `*this` and `sz`.
  989. *
  990. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  991. */
  992. BOOST_CONTAINER_FORCEINLINE void resize_front(size_type sz, default_init_t)
  993. {
  994. resize_front_impl(sz, default_init);
  995. BOOST_ASSERT(invariants_ok());
  996. }
  997. /**
  998. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  999. *
  1000. * **Effects**: If `sz` is greater than the size of `*this`,
  1001. * copies of `c` are inserted to the front.
  1002. * Invalidates iterators if reallocation is needed.
  1003. * If `sz` is smaller than than the size of `*this`,
  1004. * elements are popped from the front.
  1005. *
  1006. * **Postcondition**: `sz == size()`.
  1007. *
  1008. * **Requires**: `T` shall be [CopyInsertable] into `*this`.
  1009. *
  1010. * **Exceptions**: Strong exception guarantee.
  1011. *
  1012. * **Complexity**: Linear in the size of `*this` and `sz`.
  1013. */
  1014. BOOST_CONTAINER_FORCEINLINE void resize_front(size_type sz, const T& c)
  1015. {
  1016. resize_front_impl(sz, c);
  1017. BOOST_ASSERT(invariants_ok());
  1018. }
  1019. /**
  1020. * **Effects**: If `sz` is greater than the size of `*this`,
  1021. * additional value-initialized elements are inserted
  1022. * to the back. Invalidates iterators if reallocation is needed.
  1023. * If `sz` is smaller than than the size of `*this`,
  1024. * elements are popped from the back.
  1025. *
  1026. * **Requires**: T shall be [MoveInsertable] into *this and [DefaultConstructible].
  1027. *
  1028. * **Postcondition**: `sz == size()`.
  1029. *
  1030. * **Exceptions**: Strong exception guarantee.
  1031. *
  1032. * **Complexity**: Linear in the size of `*this` and `sz`.
  1033. *
  1034. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1035. * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
  1036. */
  1037. BOOST_CONTAINER_FORCEINLINE void resize_back(size_type sz)
  1038. {
  1039. resize_back_impl(sz);
  1040. BOOST_ASSERT(invariants_ok());
  1041. }
  1042. /**
  1043. * **Effects**: If `sz` is greater than the size of `*this`,
  1044. * additional value-initialized elements are inserted
  1045. * to the back. Invalidates iterators if reallocation is needed.
  1046. * If `sz` is smaller than than the size of `*this`,
  1047. * elements are popped from the back.
  1048. *
  1049. * **Requires**: T shall be [MoveInsertable] into *this and default initializable.
  1050. *
  1051. * **Postcondition**: `sz == size()`.
  1052. *
  1053. * **Exceptions**: Strong exception guarantee.
  1054. *
  1055. * **Complexity**: Linear in the size of `*this` and `sz`.
  1056. *
  1057. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1058. */
  1059. BOOST_CONTAINER_FORCEINLINE void resize_back(size_type sz, default_init_t)
  1060. {
  1061. resize_back_impl(sz, default_init);
  1062. BOOST_ASSERT(invariants_ok());
  1063. }
  1064. /**
  1065. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  1066. *
  1067. * **Effects**: If `sz` is greater than the size of `*this`,
  1068. * copies of `c` are inserted to the back.
  1069. * If `sz` is smaller than than the size of `*this`,
  1070. * elements are popped from the back.
  1071. *
  1072. * **Postcondition**: `sz == size()`.
  1073. *
  1074. * **Requires**: `T` shall be [CopyInsertable] into `*this`.
  1075. *
  1076. * **Exceptions**: Strong exception guarantee.
  1077. *
  1078. * **Complexity**: Linear in the size of `*this` and `sz`.
  1079. */
  1080. BOOST_CONTAINER_FORCEINLINE void resize_back(size_type sz, const T& c)
  1081. {
  1082. resize_back_impl(sz, c);
  1083. BOOST_ASSERT(invariants_ok());
  1084. }
  1085. /**
  1086. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1087. *
  1088. * **Effects**: Ensures that at least `n` elements can be inserted
  1089. * without requiring reallocation, where `n` is `new_capacity - size()`,
  1090. * if `n` is positive. Otherwise, there are no effects.
  1091. * Invalidates iterators if reallocation is needed.
  1092. *
  1093. * **Requires**: `T` shall be [MoveInsertable] into `*this`.
  1094. *
  1095. * **Complexity**: Linear in the size of *this.
  1096. *
  1097. * **Exceptions**: Strong exception guarantee.
  1098. *
  1099. * **Throws**: length_error if `new_capacity > max_size()`.
  1100. */
  1101. BOOST_CONTAINER_FORCEINLINE void reserve(size_type new_capacity)
  1102. {
  1103. if (this->capacity() < new_capacity) {
  1104. const size_type rounder = devector_min_free_fraction - 2u;
  1105. const size_type divisor = devector_min_free_fraction - 1u;
  1106. size_type const nc = ((new_capacity + rounder)/divisor)*devector_min_free_fraction;
  1107. BOOST_ASSERT(new_capacity <= (nc - nc / devector_min_free_fraction));
  1108. size_type const sz = this->size();
  1109. reallocate_at(nc, (nc-sz)/2u);
  1110. }
  1111. BOOST_ASSERT(invariants_ok());
  1112. }
  1113. /**
  1114. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1115. *
  1116. * **Effects**: Ensures that `n` elements can be pushed to the front
  1117. * without requiring reallocation, where `n` is `new_capacity - size()`,
  1118. * if `n` is positive. Otherwise, there are no effects.
  1119. * Invalidates iterators if reallocation is needed.
  1120. *
  1121. * **Requires**: `T` shall be [MoveInsertable] into `*this`.
  1122. *
  1123. * **Complexity**: Linear in the size of *this.
  1124. *
  1125. * **Exceptions**: Strong exception guarantee.
  1126. *
  1127. * **Throws**: `length_error` if `new_capacity > max_size()`.
  1128. */
  1129. BOOST_CONTAINER_FORCEINLINE void reserve_front(size_type new_capacity)
  1130. {
  1131. if (front_capacity() >= new_capacity) { return; }
  1132. reallocate_at(new_capacity + back_free_capacity(), new_capacity - size());
  1133. BOOST_ASSERT(invariants_ok());
  1134. }
  1135. /**
  1136. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1137. *
  1138. * **Effects**: Ensures that `n` elements can be pushed to the back
  1139. * without requiring reallocation, where `n` is `new_capacity - size()`,
  1140. * if `n` is positive. Otherwise, there are no effects.
  1141. * Invalidates iterators if reallocation is needed.
  1142. *
  1143. * **Requires**: `T` shall be [MoveInsertable] into `*this`.
  1144. *
  1145. * **Complexity**: Linear in the size of *this.
  1146. *
  1147. * **Exceptions**: Strong exception guarantee.
  1148. *
  1149. * **Throws**: length_error if `new_capacity > max_size()`.
  1150. */
  1151. BOOST_CONTAINER_FORCEINLINE void reserve_back(size_type new_capacity)
  1152. {
  1153. if (back_capacity() >= new_capacity) { return; }
  1154. reallocate_at(new_capacity + front_free_capacity(), m_.front_idx);
  1155. BOOST_ASSERT(invariants_ok());
  1156. }
  1157. /**
  1158. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1159. *
  1160. * **Effects**: Reduces `capacity()` to `size()`. Invalidates iterators.
  1161. *
  1162. * **Requires**: `T` shall be [MoveInsertable] into `*this`.
  1163. *
  1164. * **Exceptions**: Strong exception guarantee.
  1165. *
  1166. * **Complexity**: Linear in the size of *this.
  1167. */
  1168. BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
  1169. {
  1170. if(this->front_capacity() || this->back_capacity())
  1171. this->reallocate_at(size(), 0);
  1172. }
  1173. // element access:
  1174. /**
  1175. * **Returns**: A reference to the `n`th element in the devector.
  1176. *
  1177. * **Precondition**: `n < size()`.
  1178. *
  1179. * **Complexity**: Constant.
  1180. */
  1181. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1182. reference operator[](size_type n) BOOST_NOEXCEPT
  1183. {
  1184. BOOST_ASSERT(n < size());
  1185. return m_.buffer[m_.front_idx + n];
  1186. }
  1187. /**
  1188. * **Returns**: A constant reference to the `n`th element in the devector.
  1189. *
  1190. * **Precondition**: `n < size()`.
  1191. *
  1192. * **Complexity**: Constant.
  1193. */
  1194. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1195. const_reference operator[](size_type n) const BOOST_NOEXCEPT
  1196. {
  1197. BOOST_ASSERT(n < size());
  1198. return m_.buffer[m_.front_idx + n];
  1199. }
  1200. /**
  1201. * **Returns**: A reference to the `n`th element in the devector.
  1202. *
  1203. * **Throws**: `out_of_range`, if `n >= size()`.
  1204. *
  1205. * **Complexity**: Constant.
  1206. */
  1207. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1208. reference at(size_type n)
  1209. {
  1210. if (size() <= n)
  1211. throw_out_of_range("devector::at out of range");
  1212. return (*this)[n];
  1213. }
  1214. /**
  1215. * **Returns**: A constant reference to the `n`th element in the devector.
  1216. *
  1217. * **Throws**: `out_of_range`, if `n >= size()`.
  1218. *
  1219. * **Complexity**: Constant.
  1220. */
  1221. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1222. const_reference at(size_type n) const
  1223. {
  1224. if (size() <= n)
  1225. throw_out_of_range("devector::at out of range");
  1226. return (*this)[n];
  1227. }
  1228. /**
  1229. * **Returns**: A reference to the first element in the devector.
  1230. *
  1231. * **Precondition**: `!empty()`.
  1232. *
  1233. * **Complexity**: Constant.
  1234. */
  1235. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1236. reference front() BOOST_NOEXCEPT
  1237. {
  1238. BOOST_ASSERT(!empty());
  1239. return m_.buffer[m_.front_idx];
  1240. }
  1241. /**
  1242. * **Returns**: A constant reference to the first element in the devector.
  1243. *
  1244. * **Precondition**: `!empty()`.
  1245. *
  1246. * **Complexity**: Constant.
  1247. */
  1248. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1249. const_reference front() const BOOST_NOEXCEPT
  1250. {
  1251. BOOST_ASSERT(!empty());
  1252. return m_.buffer[m_.front_idx];
  1253. }
  1254. /**
  1255. * **Returns**: A reference to the last element in the devector.
  1256. *
  1257. * **Precondition**: `!empty()`.
  1258. *
  1259. * **Complexity**: Constant.
  1260. */
  1261. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1262. reference back() BOOST_NOEXCEPT
  1263. {
  1264. BOOST_ASSERT(!empty());
  1265. return m_.buffer[m_.back_idx - 1u];
  1266. }
  1267. /**
  1268. * **Returns**: A constant reference to the last element in the devector.
  1269. *
  1270. * **Precondition**: `!empty()`.
  1271. *
  1272. * **Complexity**: Constant.
  1273. */
  1274. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1275. const_reference back() const BOOST_NOEXCEPT
  1276. {
  1277. BOOST_ASSERT(!empty());
  1278. return m_.buffer[m_.back_idx - 1u];
  1279. }
  1280. /**
  1281. * **Returns**: A pointer to the underlying array serving as element storage.
  1282. * The range `[data(); data() + size())` is always valid. For a non-empty devector,
  1283. * `data() == &front()`.
  1284. *
  1285. * **Complexity**: Constant.
  1286. */
  1287. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1288. T* data() BOOST_NOEXCEPT
  1289. {
  1290. return boost::movelib::to_raw_pointer(m_.buffer) + m_.front_idx;
  1291. }
  1292. /**
  1293. * **Returns**: A constant pointer to the underlying array serving as element storage.
  1294. * The range `[data(); data() + size())` is always valid. For a non-empty devector,
  1295. * `data() == &front()`.
  1296. *
  1297. * **Complexity**: Constant.
  1298. */
  1299. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1300. const T* data() const BOOST_NOEXCEPT
  1301. {
  1302. return boost::movelib::to_raw_pointer(m_.buffer) + m_.front_idx;
  1303. }
  1304. // modifiers:
  1305. /**
  1306. * **Effects**: Pushes a new element to the front of the devector.
  1307. * The element is constructed in-place, using the perfect forwarded `args`
  1308. * as constructor arguments. Invalidates iterators if reallocation is needed.
  1309. * (`front_free_capacity() == 0`)
  1310. *
  1311. * **Requires**: `T` shall be [EmplaceConstructible] from `args` and [MoveInsertable] into `*this`.
  1312. *
  1313. * **Exceptions**: Strong exception guarantee.
  1314. *
  1315. * **Complexity**: Amortized constant in the size of `*this`.
  1316. * (Constant, if `front_free_capacity() > 0`)
  1317. *
  1318. * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
  1319. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1320. */
  1321. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1322. template <class... Args>
  1323. reference emplace_front(Args&&... args)
  1324. {
  1325. if (BOOST_LIKELY(front_free_capacity() != 0)) // fast path
  1326. {
  1327. pointer const p = m_.buffer + (m_.front_idx - 1u);
  1328. this->alloc_construct(p, boost::forward<Args>(args)...);
  1329. --m_.front_idx;
  1330. BOOST_ASSERT(invariants_ok());
  1331. return *p;
  1332. }
  1333. else
  1334. {
  1335. typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
  1336. return *this->insert_range_slow_path(this->begin(), 1, proxy_t(::boost::forward<Args>(args)...));
  1337. }
  1338. }
  1339. #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1340. #define BOOST_CONTAINER_DEVECTOR_EMPLACE_FRONT(N) \
  1341. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  1342. BOOST_CONTAINER_FORCEINLINE reference emplace_front(BOOST_MOVE_UREF##N)\
  1343. {\
  1344. if (front_free_capacity())\
  1345. {\
  1346. pointer const p = m_.buffer + (m_.front_idx - 1u);\
  1347. this->alloc_construct(p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  1348. --m_.front_idx;\
  1349. return *p;\
  1350. }\
  1351. else\
  1352. {\
  1353. typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
  1354. return *this->insert_range_slow_path(this->begin(), 1, proxy_t(BOOST_MOVE_FWD##N));\
  1355. }\
  1356. }\
  1357. //
  1358. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_EMPLACE_FRONT)
  1359. #undef BOOST_CONTAINER_DEVECTOR_EMPLACE_FRONT
  1360. #endif
  1361. #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1362. /**
  1363. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  1364. *
  1365. * **Effects**: Pushes the copy of `x` to the front of the devector.
  1366. * Invalidates iterators if reallocation is needed.
  1367. * (`front_free_capacity() == 0`)
  1368. *
  1369. * **Requires**: `T` shall be [CopyInsertable] into `*this`.
  1370. *
  1371. * **Exceptions**: Strong exception guarantee.
  1372. *
  1373. * **Complexity**: Amortized constant in the size of `*this`.
  1374. * (Constant, if `front_free_capacity() > 0`)
  1375. */
  1376. void push_front(const T& x);
  1377. /**
  1378. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1379. *
  1380. * **Effects**: Move constructs a new element at the front of the devector using `x`.
  1381. * Invalidates iterators if reallocation is needed.
  1382. * (`front_free_capacity() == 0`)
  1383. *
  1384. * **Requires**: `T` shall be [MoveInsertable] into `*this`.
  1385. *
  1386. * **Exceptions**: Strong exception guarantee, not regarding the state of `x`.
  1387. *
  1388. * **Complexity**: Amortized constant in the size of `*this`.
  1389. * (Constant, if `front_free_capacity() > 0`)
  1390. */
  1391. void push_front(T&& x);
  1392. #else
  1393. BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front)
  1394. #endif
  1395. /**
  1396. * **Effects**: Removes the first element of `*this`.
  1397. *
  1398. * **Precondition**: `!empty()`.
  1399. *
  1400. * **Postcondition**: `front_free_capacity()` is incremented by 1.
  1401. *
  1402. * **Complexity**: Constant.
  1403. */
  1404. void pop_front() BOOST_NOEXCEPT
  1405. {
  1406. BOOST_ASSERT(!empty());
  1407. allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(m_.buffer + m_.front_idx));
  1408. ++m_.front_idx;
  1409. BOOST_ASSERT(invariants_ok());
  1410. }
  1411. /**
  1412. * **Effects**: Pushes a new element to the back of the devector.
  1413. * The element is constructed in-place, using the perfect forwarded `args`
  1414. * as constructor arguments. Invalidates iterators if reallocation is needed.
  1415. * (`back_free_capacity() == 0`)
  1416. *
  1417. * **Requires**: `T` shall be [EmplaceConstructible] from `args` and [MoveInsertable] into `*this`,
  1418. * and [MoveAssignable].
  1419. *
  1420. * **Exceptions**: Strong exception guarantee.
  1421. *
  1422. * **Complexity**: Amortized constant in the size of `*this`.
  1423. * (Constant, if `back_free_capacity() > 0`)
  1424. *
  1425. * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
  1426. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1427. * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
  1428. */
  1429. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1430. template <class... Args>
  1431. BOOST_CONTAINER_FORCEINLINE reference emplace_back(Args&&... args)
  1432. {
  1433. if (BOOST_LIKELY(this->back_free_capacity() != 0)){
  1434. pointer const p = m_.buffer + m_.back_idx;
  1435. this->alloc_construct(p, boost::forward<Args>(args)...);
  1436. ++m_.back_idx;
  1437. BOOST_ASSERT(invariants_ok());
  1438. return *p;
  1439. }
  1440. else {
  1441. typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
  1442. return *this->insert_range_slow_path(this->end(), 1, proxy_t(::boost::forward<Args>(args)...));
  1443. }
  1444. }
  1445. #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1446. #define BOOST_CONTAINER_DEVECTOR_EMPLACE_BACK(N) \
  1447. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  1448. BOOST_CONTAINER_FORCEINLINE reference emplace_back(BOOST_MOVE_UREF##N)\
  1449. {\
  1450. if (this->back_free_capacity()){\
  1451. pointer const p = m_.buffer + m_.back_idx;\
  1452. this->alloc_construct(p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  1453. ++m_.back_idx;\
  1454. return *p;\
  1455. }\
  1456. else {\
  1457. typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
  1458. return *this->insert_range_slow_path(this->end(), 1, proxy_t(BOOST_MOVE_FWD##N));\
  1459. }\
  1460. }\
  1461. //
  1462. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_EMPLACE_BACK)
  1463. #undef BOOST_CONTAINER_DEVECTOR_EMPLACE_BACK
  1464. #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1465. #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1466. /**
  1467. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  1468. *
  1469. * **Effects**: Pushes the copy of `x` to the back of the devector.
  1470. * Invalidates iterators if reallocation is needed.
  1471. * (`back_free_capacity() == 0`)
  1472. *
  1473. * **Requires**: `T` shall be [CopyInsertable] into `*this`.
  1474. *
  1475. * **Exceptions**: Strong exception guarantee.
  1476. *
  1477. * **Complexity**: Amortized constant in the size of `*this`.
  1478. * (Constant, if `back_free_capacity() > 0`)
  1479. */
  1480. void push_back(const T& x);
  1481. /**
  1482. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1483. *
  1484. * **Effects**: Move constructs a new element at the back of the devector using `x`.
  1485. * Invalidates iterators if reallocation is needed.
  1486. * (`back_free_capacity() == 0`)
  1487. *
  1488. * **Requires**: `T` shall be [MoveInsertable] into `*this`.
  1489. *
  1490. * **Exceptions**: Strong exception guarantee, not regarding the state of `x`.
  1491. *
  1492. * **Complexity**: Amortized constant in the size of `*this`.
  1493. * (Constant, if `back_free_capacity() > 0`)
  1494. */
  1495. void push_back(T&& x);
  1496. #else
  1497. BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
  1498. #endif
  1499. /**
  1500. * **Effects**: Removes the last element of `*this`.
  1501. *
  1502. * **Precondition**: `!empty()`.
  1503. *
  1504. * **Postcondition**: `back_free_capacity()` is incremented by 1.
  1505. *
  1506. * **Complexity**: Constant.
  1507. */
  1508. void pop_back() BOOST_NOEXCEPT
  1509. {
  1510. BOOST_ASSERT(! empty());
  1511. --m_.back_idx;
  1512. allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(m_.buffer + m_.back_idx));
  1513. BOOST_ASSERT(invariants_ok());
  1514. }
  1515. /**
  1516. * **Effects**: Constructs a new element before the element pointed by `position`.
  1517. * The element is constructed in-place, using the perfect forwarded `args`
  1518. * as constructor arguments. Invalidates iterators if reallocation is needed.
  1519. *
  1520. * **Requires**: `T` shall be [EmplaceConstructible], and [MoveInsertable] into `*this`,
  1521. * and [MoveAssignable].
  1522. *
  1523. * **Returns**: Iterator pointing to the newly constructed element.
  1524. *
  1525. * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
  1526. * and `NothrowAssignable`, Basic exception guarantee otherwise.
  1527. *
  1528. * **Complexity**: Linear in the size of `*this`.
  1529. *
  1530. * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
  1531. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1532. * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
  1533. */
  1534. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1535. template <class... Args>
  1536. iterator emplace(const_iterator position, Args&&... args)
  1537. {
  1538. BOOST_ASSERT(position >= begin());
  1539. BOOST_ASSERT(position <= end());
  1540. typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
  1541. bool prefer_move_back;
  1542. if (position == end()){
  1543. if(back_free_capacity()) // fast path
  1544. {
  1545. pointer const p = m_.buffer + m_.back_idx;
  1546. this->alloc_construct(p, boost::forward<Args>(args)...);
  1547. ++m_.back_idx;
  1548. return iterator(p);
  1549. }
  1550. prefer_move_back = true;
  1551. }
  1552. else if (position == begin()){
  1553. if(front_free_capacity()) // secondary fast path
  1554. {
  1555. pointer const p = m_.buffer + (m_.front_idx - 1);
  1556. this->alloc_construct(p, boost::forward<Args>(args)...);
  1557. --m_.front_idx;
  1558. return iterator(p);
  1559. }
  1560. prefer_move_back = false;
  1561. }
  1562. else{
  1563. iterator nonconst_pos = unconst_iterator(position);
  1564. prefer_move_back = should_move_back(position);
  1565. if(prefer_move_back){
  1566. if(back_free_capacity()){
  1567. boost::container::expand_forward_and_insert_nonempty_middle_alloc
  1568. ( get_allocator_ref()
  1569. , boost::movelib::to_raw_pointer(nonconst_pos)
  1570. , this->priv_raw_end()
  1571. , 1, proxy_t(::boost::forward<Args>(args)...));
  1572. ++m_.back_idx;
  1573. return nonconst_pos;
  1574. }
  1575. }
  1576. else{
  1577. if (front_free_capacity()){
  1578. boost::container::expand_backward_and_insert_nonempty_middle_alloc
  1579. (get_allocator_ref()
  1580. , this->priv_raw_begin()
  1581. , boost::movelib::to_raw_pointer(nonconst_pos)
  1582. , 1, proxy_t(::boost::forward<Args>(args)...));
  1583. --m_.front_idx;
  1584. return --nonconst_pos;
  1585. }
  1586. }
  1587. }
  1588. return this->insert_range_slow_path(position, 1, proxy_t(::boost::forward<Args>(args)...));
  1589. }
  1590. #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1591. #define BOOST_CONTAINER_DEVECTOR_EMPLACE(N) \
  1592. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  1593. iterator emplace(const_iterator position BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  1594. {\
  1595. BOOST_ASSERT(position >= begin());\
  1596. BOOST_ASSERT(position <= end());\
  1597. typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
  1598. bool prefer_move_back;\
  1599. if (position == end()){\
  1600. if(back_free_capacity())\
  1601. {\
  1602. pointer const p = m_.buffer + m_.back_idx;\
  1603. this->alloc_construct(p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  1604. ++m_.back_idx;\
  1605. return iterator(p);\
  1606. }\
  1607. prefer_move_back = true;\
  1608. }\
  1609. else if (position == begin()){\
  1610. if(front_free_capacity())\
  1611. {\
  1612. pointer const p = m_.buffer + (m_.front_idx - 1);\
  1613. this->alloc_construct(p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  1614. --m_.front_idx;\
  1615. return iterator(p);\
  1616. }\
  1617. prefer_move_back = false;\
  1618. }\
  1619. else{\
  1620. iterator nonconst_pos = unconst_iterator(position);\
  1621. prefer_move_back = should_move_back(position);\
  1622. \
  1623. if(prefer_move_back){\
  1624. if(back_free_capacity()){\
  1625. boost::container::expand_forward_and_insert_nonempty_middle_alloc\
  1626. ( get_allocator_ref()\
  1627. , boost::movelib::to_raw_pointer(nonconst_pos)\
  1628. , this->priv_raw_end()\
  1629. , 1, proxy_t(BOOST_MOVE_FWD##N));\
  1630. ++m_.back_idx;\
  1631. return nonconst_pos;\
  1632. }\
  1633. }\
  1634. else{\
  1635. if (front_free_capacity()){\
  1636. boost::container::expand_backward_and_insert_nonempty_middle_alloc\
  1637. (get_allocator_ref()\
  1638. , this->priv_raw_begin()\
  1639. , boost::movelib::to_raw_pointer(nonconst_pos)\
  1640. , 1, proxy_t(BOOST_MOVE_FWD##N));\
  1641. --m_.front_idx;\
  1642. return --nonconst_pos;\
  1643. }\
  1644. }\
  1645. }\
  1646. return this->insert_range_slow_path(position, 1, proxy_t(BOOST_MOVE_FWD##N));\
  1647. }\
  1648. //
  1649. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_EMPLACE)
  1650. #undef BOOST_CONTAINER_DEVECTOR_EMPLACE
  1651. #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1652. #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1653. /**
  1654. * **Effects**: Copy constructs a new element before the element pointed by `position`,
  1655. * using `x` as constructor argument. Invalidates iterators if reallocation is needed.
  1656. *
  1657. * **Requires**: `T` shall be [CopyInsertable] into `*this` and and [CopyAssignable].
  1658. *
  1659. * **Returns**: Iterator pointing to the newly constructed element.
  1660. *
  1661. * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
  1662. * and `NothrowAssignable`, Basic exception guarantee otherwise.
  1663. *
  1664. * **Complexity**: Linear in the size of `*this`.
  1665. *
  1666. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  1667. * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
  1668. */
  1669. iterator insert(const_iterator position, const T &x);
  1670. /**
  1671. * **Effects**: Move constructs a new element before the element pointed by `position`,
  1672. * using `x` as constructor argument. Invalidates iterators if reallocation is needed.
  1673. *
  1674. * **Requires**: `T` shall be [MoveInsertable] into `*this` and and [CopyAssignable].
  1675. *
  1676. * **Returns**: Iterator pointing to the newly constructed element.
  1677. *
  1678. * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
  1679. * and `NothrowAssignable` (not regarding the state of `x`),
  1680. * Basic exception guarantee otherwise.
  1681. *
  1682. * **Complexity**: Linear in the size of `*this`.
  1683. *
  1684. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1685. * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
  1686. */
  1687. iterator insert(const_iterator position, T &&x);
  1688. #else
  1689. BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
  1690. #endif
  1691. /**
  1692. * **Effects**: Copy constructs `n` elements before the element pointed by `position`,
  1693. * using `x` as constructor argument. Invalidates iterators if reallocation is needed.
  1694. *
  1695. * **Requires**: `T` shall be [CopyInsertable] into `*this` and and [CopyAssignable].
  1696. *
  1697. * **Returns**: Iterator pointing to the first inserted element, or `position`, if `n` is zero.
  1698. *
  1699. * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
  1700. * and `NothrowAssignable`, Basic exception guarantee otherwise.
  1701. *
  1702. * **Complexity**: Linear in the size of `*this` and `n`.
  1703. *
  1704. * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
  1705. * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
  1706. */
  1707. BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator position, size_type n, const T& x)
  1708. {
  1709. cvalue_iterator first(x, n);
  1710. cvalue_iterator last = first + n;
  1711. return this->insert_range(position, first, last);
  1712. }
  1713. /**
  1714. * **Effects**: Copy constructs elements before the element pointed by position
  1715. * using each element in the range pointed by `first` and `last` as constructor arguments.
  1716. * Invalidates iterators if reallocation is needed.
  1717. *
  1718. * **Requires**: `T` shall be [EmplaceConstructible] into `*this` from `*first`. If the specified iterator
  1719. * does not meet the forward iterator requirements, `T` shall also be [MoveInsertable] into `*this`
  1720. * and [MoveAssignable].
  1721. *
  1722. * **Precondition**: `first` and `last` are not iterators into `*this`.
  1723. *
  1724. * **Returns**: Iterator pointing to the first inserted element, or `position`, if `first == last`.
  1725. *
  1726. * **Complexity**: Linear in the size of `*this` and `N` (where `N` is the distance between `first` and `last`).
  1727. * Makes only `N` calls to the constructor of `T` and no reallocations if iterators `first` and `last`
  1728. * are of forward, bidirectional, or random access categories. It makes 2N calls to the copy constructor of `T`
  1729. * and `O(log(N)) reallocations if they are just input iterators.
  1730. *
  1731. * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
  1732. * and `NothrowAssignable`, Basic exception guarantee otherwise.
  1733. *
  1734. * **Remarks**: Each iterator in the range `[first,last)` shall be dereferenced exactly once,
  1735. * unless an exception is thrown.
  1736. *
  1737. * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
  1738. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1739. * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
  1740. */
  1741. template <class InputIterator>
  1742. iterator insert(const_iterator position, InputIterator first, InputIterator last
  1743. //Input iterators
  1744. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
  1745. < void
  1746. BOOST_MOVE_I dtl::is_convertible<InputIterator BOOST_MOVE_I size_type>
  1747. BOOST_MOVE_I dtl::is_not_input_iterator<InputIterator>
  1748. >::type * = 0)
  1749. )
  1750. {
  1751. if (position == end())
  1752. {
  1753. size_type insert_index = size();
  1754. for (; first != last; ++first)
  1755. {
  1756. this->emplace_back(*first);
  1757. }
  1758. return begin() + insert_index;
  1759. }
  1760. else
  1761. {
  1762. const size_type insert_index = static_cast<size_type>(position - this->cbegin());
  1763. const size_type old_size = static_cast<size_type>(this->size());
  1764. for (; first != last; ++first) {
  1765. this->emplace_back(*first);
  1766. }
  1767. iterator rit (this->begin() + insert_index);
  1768. boost::movelib::rotate_gcd(rit, this->begin() + old_size, this->begin() + this->size());
  1769. return rit;
  1770. }
  1771. }
  1772. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  1773. template <class ForwardIterator>
  1774. BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator position, ForwardIterator first, ForwardIterator last
  1775. //Other iterators
  1776. BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
  1777. < void
  1778. BOOST_MOVE_I dtl::is_convertible<ForwardIterator BOOST_MOVE_I size_type>
  1779. BOOST_MOVE_I dtl::is_input_iterator<ForwardIterator>
  1780. >::type * = 0)
  1781. )
  1782. {
  1783. return insert_range(position, first, last);
  1784. }
  1785. #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  1786. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  1787. /** **Equivalent to**: `insert(position, il.begin(), il.end())` */
  1788. BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator position, std::initializer_list<T> il)
  1789. {
  1790. return this->insert(position, il.begin(), il.end());
  1791. }
  1792. #endif
  1793. /**
  1794. * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
  1795. *
  1796. * **Effects**: Destroys the element pointed by `position` and removes it from the devector.
  1797. * Invalidates iterators.
  1798. *
  1799. * **Requires**: `T` shall be [MoveAssignable].
  1800. *
  1801. * **Precondition**: `position` must be in the range of `[begin(), end())`.
  1802. *
  1803. * **Returns**: Iterator pointing to the element immediately following the erased element
  1804. * prior to its erasure. If no such element exists, `end()` is returned.
  1805. *
  1806. * **Exceptions**: Strong exception guarantee if `T` is `NothrowAssignable`,
  1807. * Basic exception guarantee otherwise.
  1808. *
  1809. * **Complexity**: Linear in half the size of `*this`.
  1810. */
  1811. iterator erase(const_iterator position)
  1812. {
  1813. return erase(position, position + 1);
  1814. }
  1815. /**
  1816. * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
  1817. *
  1818. * **Effects**: Destroys the range `[first,last)` and removes it from the devector.
  1819. * Invalidates iterators.
  1820. *
  1821. * **Requires**: `T` shall be [MoveAssignable].
  1822. *
  1823. * **Precondition**: `[first,last)` must be in the range of `[begin(), end())`.
  1824. *
  1825. * **Returns**: Iterator pointing to the element pointed to by `last` prior to any elements
  1826. * being erased. If no such element exists, `end()` is returned.
  1827. *
  1828. * **Exceptions**: Strong exception guarantee if `T` is `NothrowAssignable`,
  1829. * Basic exception guarantee otherwise.
  1830. *
  1831. * **Complexity**: Linear in half the size of `*this`
  1832. * plus the distance between `first` and `last`.
  1833. */
  1834. iterator erase(const_iterator first, const_iterator last)
  1835. {
  1836. iterator nc_first = unconst_iterator(first);
  1837. iterator nc_last = unconst_iterator(last);
  1838. return erase(nc_first, nc_last);
  1839. }
  1840. /**
  1841. * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
  1842. *
  1843. * **Effects**: Destroys the range `[first,last)` and removes it from the devector.
  1844. * Invalidates iterators.
  1845. *
  1846. * **Requires**: `T` shall be [MoveAssignable].
  1847. *
  1848. * **Precondition**: `[first,last)` must be in the range of `[begin(), end())`.
  1849. *
  1850. * **Returns**: Iterator pointing to the element pointed to by `last` prior to any elements
  1851. * being erased. If no such element exists, `end()` is returned.
  1852. *
  1853. * **Exceptions**: Strong exception guarantee if `T` is `NothrowAssignable`,
  1854. * Basic exception guarantee otherwise.
  1855. *
  1856. * **Complexity**: Linear in half the size of `*this`.
  1857. */
  1858. iterator erase(iterator first, iterator last)
  1859. {
  1860. size_type front_distance = pos_to_index(last);
  1861. size_type back_distance = size_type(end() - first);
  1862. size_type n = boost::container::iterator_udistance(first, last);
  1863. if (front_distance < back_distance)
  1864. {
  1865. // move n to the right
  1866. boost::container::move_backward(begin(), first, last);
  1867. for (iterator i = begin(); i != begin() + n; ++i)
  1868. {
  1869. allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(i));
  1870. }
  1871. //n is always less than max stored_size_type
  1872. m_.set_front_idx(m_.front_idx + n);
  1873. BOOST_ASSERT(invariants_ok());
  1874. return last;
  1875. }
  1876. else {
  1877. // move n to the left
  1878. boost::container::move(last, end(), first);
  1879. for (iterator i = end() - n; i != end(); ++i)
  1880. {
  1881. allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(i));
  1882. }
  1883. //n is always less than max stored_size_type
  1884. m_.set_back_idx(m_.back_idx - n);
  1885. BOOST_ASSERT(invariants_ok());
  1886. return first;
  1887. }
  1888. }
  1889. /**
  1890. * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
  1891. *
  1892. * **Effects**: exchanges the contents of `*this` and `b`.
  1893. *
  1894. * **Requires**: instances of `T` must be swappable by unqualified call of `swap`
  1895. * and `T` must be [MoveInsertable] into `*this`.
  1896. *
  1897. * **Precondition**: The allocators should allow propagation or should compare equal.
  1898. *
  1899. * **Exceptions**: Basic exceptions guarantee if not `noexcept`.
  1900. *
  1901. * **Complexity**: Constant.
  1902. */
  1903. void swap(devector& b)
  1904. BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
  1905. || allocator_traits_type::is_always_equal::value)
  1906. {
  1907. BOOST_CONSTEXPR_OR_CONST bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value;
  1908. BOOST_ASSERT(propagate_alloc || get_allocator_ref() == b.get_allocator_ref()); // else it's undefined behavior
  1909. swap_big_big(*this, b);
  1910. // swap indices
  1911. boost::adl_move_swap(m_.front_idx, b.m_.front_idx);
  1912. boost::adl_move_swap(m_.back_idx, b.m_.back_idx);
  1913. //And now swap the allocator
  1914. dtl::swap_alloc(this->get_allocator_ref(), b.get_allocator_ref(), dtl::bool_<propagate_alloc>());
  1915. BOOST_ASSERT( invariants_ok());
  1916. BOOST_ASSERT(b.invariants_ok());
  1917. }
  1918. /**
  1919. * **Effects**: Destroys all elements in the devector.
  1920. * Invalidates all references, pointers and iterators to the
  1921. * elements of the devector.
  1922. *
  1923. * **Postcondition**: `empty() && front_free_capacity() == 0
  1924. * && back_free_capacity() == old capacity`.
  1925. *
  1926. * **Complexity**: Linear in the size of `*this`.
  1927. *
  1928. * **Remarks**: Does not free memory.
  1929. */
  1930. void clear() BOOST_NOEXCEPT
  1931. {
  1932. destroy_elements(begin(), end());
  1933. m_.front_idx = m_.back_idx = 0;
  1934. }
  1935. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1936. friend bool operator==(const devector& x, const devector& y)
  1937. { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
  1938. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1939. friend bool operator!=(const devector& x, const devector& y)
  1940. { return !(x == y); }
  1941. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1942. friend bool operator< (const devector& x, const devector& y)
  1943. { return boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
  1944. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1945. friend bool operator>(const devector& x, const devector& y)
  1946. { return y < x; }
  1947. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1948. friend bool operator<=(const devector& x, const devector& y)
  1949. { return !(y < x); }
  1950. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1951. friend bool operator>=(const devector& x, const devector& y)
  1952. { return !(x < y); }
  1953. BOOST_CONTAINER_FORCEINLINE friend void swap(devector& x, devector& y)
  1954. BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
  1955. || allocator_traits_type::is_always_equal::value)
  1956. { x.swap(y); }
  1957. private:
  1958. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1959. size_type pos_to_index(const_iterator i) const
  1960. {
  1961. return static_cast<size_type>(i - cbegin());
  1962. }
  1963. BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
  1964. bool should_move_back(const_iterator i) const
  1965. {
  1966. return static_cast<size_type>(this->pos_to_index(i)) >= this->size()/2u;
  1967. }
  1968. BOOST_CONTAINER_FORCEINLINE static iterator unconst_iterator(const_iterator i)
  1969. {
  1970. return boost::intrusive::pointer_traits<pointer>::const_cast_from(i);
  1971. }
  1972. BOOST_CONTAINER_FORCEINLINE size_type front_capacity() const
  1973. {
  1974. return m_.back_idx;
  1975. }
  1976. BOOST_CONTAINER_FORCEINLINE size_type back_capacity() const
  1977. {
  1978. return size_type(m_.capacity - m_.front_idx);
  1979. }
  1980. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  1981. BOOST_CONTAINER_FORCEINLINE T* priv_raw_begin() BOOST_NOEXCEPT
  1982. { return boost::movelib::to_raw_pointer(m_.buffer) + m_.front_idx; }
  1983. BOOST_CONTAINER_FORCEINLINE T* priv_raw_end() BOOST_NOEXCEPT
  1984. { return boost::movelib::to_raw_pointer(m_.buffer) + m_.back_idx; }
  1985. template <class U>
  1986. BOOST_CONTAINER_FORCEINLINE void priv_push_front(BOOST_FWD_REF(U) u)
  1987. {
  1988. this->emplace_front(boost::forward<U>(u));
  1989. }
  1990. template <class U>
  1991. BOOST_CONTAINER_FORCEINLINE void priv_push_back(BOOST_FWD_REF(U) u)
  1992. {
  1993. this->emplace_back(boost::forward<U>(u));
  1994. }
  1995. template <class U>
  1996. BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator pos, BOOST_FWD_REF(U) u)
  1997. {
  1998. return this->emplace(pos, boost::forward<U>(u));
  1999. }
  2000. // allocator_type wrappers
  2001. BOOST_CONTAINER_FORCEINLINE allocator_type& get_allocator_ref() BOOST_NOEXCEPT
  2002. {
  2003. return static_cast<allocator_type&>(m_);
  2004. }
  2005. BOOST_CONTAINER_FORCEINLINE const allocator_type& get_allocator_ref() const BOOST_NOEXCEPT
  2006. {
  2007. return static_cast<const allocator_type&>(m_);
  2008. }
  2009. pointer allocate(size_type capacity)
  2010. {
  2011. pointer const p = impl::do_allocate(get_allocator_ref(), capacity);
  2012. #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2013. ++m_.capacity_alloc_count;
  2014. #endif // BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2015. return p;
  2016. }
  2017. void destroy_elements(pointer begin, pointer end)
  2018. {
  2019. for (; begin != end; ++begin)
  2020. {
  2021. allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(begin));
  2022. }
  2023. }
  2024. void deallocate_buffer()
  2025. {
  2026. if (m_.buffer)
  2027. {
  2028. allocator_traits_type::deallocate(get_allocator_ref(), m_.buffer, m_.capacity);
  2029. }
  2030. }
  2031. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  2032. template <typename... Args>
  2033. BOOST_CONTAINER_FORCEINLINE void alloc_construct(pointer dst, Args&&... args)
  2034. {
  2035. allocator_traits_type::construct(
  2036. get_allocator_ref(),
  2037. boost::movelib::to_raw_pointer(dst),
  2038. boost::forward<Args>(args)...
  2039. );
  2040. }
  2041. template <typename... Args>
  2042. void construct_n(pointer buffer, size_type n, Args&&... args)
  2043. {
  2044. detail::construction_guard<allocator_type> ctr_guard(buffer, get_allocator_ref());
  2045. guarded_construct_n(buffer, n, ctr_guard, boost::forward<Args>(args)...);
  2046. ctr_guard.release();
  2047. }
  2048. template <typename... Args>
  2049. void guarded_construct_n(pointer buffer, size_type n, detail::construction_guard<allocator_type>& ctr_guard, Args&&... args)
  2050. {
  2051. for (size_type i = 0; i < n; ++i) {
  2052. this->alloc_construct(buffer + i, boost::forward<Args>(args)...);
  2053. ctr_guard.extend();
  2054. }
  2055. }
  2056. #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  2057. #define BOOST_CONTAINER_DEVECTOR_ALLOC_CONSTRUCT(N) \
  2058. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  2059. BOOST_CONTAINER_FORCEINLINE void alloc_construct(pointer dst BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  2060. {\
  2061. allocator_traits_type::construct(\
  2062. get_allocator_ref(), boost::movelib::to_raw_pointer(dst) BOOST_MOVE_I##N BOOST_MOVE_FWD##N );\
  2063. }\
  2064. \
  2065. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  2066. void construct_n(pointer buffer, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  2067. {\
  2068. detail::construction_guard<allocator_type> ctr_guard(buffer, get_allocator_ref());\
  2069. guarded_construct_n(buffer, n, ctr_guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  2070. ctr_guard.release();\
  2071. }\
  2072. \
  2073. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  2074. void guarded_construct_n(pointer buffer, size_type n, detail::construction_guard<allocator_type>& ctr_guard BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  2075. {\
  2076. for (size_type i = 0; i < n; ++i) {\
  2077. this->alloc_construct(buffer + i BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  2078. ctr_guard.extend();\
  2079. }\
  2080. }
  2081. //
  2082. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_ALLOC_CONSTRUCT)
  2083. #undef BOOST_CONTAINER_DEVECTOR_ALLOC_CONSTRUCT
  2084. #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  2085. size_type calculate_new_capacity(size_type requested_capacity)
  2086. {
  2087. size_type max = allocator_traits_type::max_size(this->get_allocator_ref());
  2088. (clamp_by_stored_size_type)(max, stored_size_type());
  2089. const size_type remaining_additional_cap = max - size_type(m_.capacity);
  2090. const size_type min_additional_cap = requested_capacity - size_type(m_.capacity);
  2091. if ( remaining_additional_cap < min_additional_cap )
  2092. boost::container::throw_length_error("devector: get_next_capacity, max size exceeded");
  2093. return growth_factor_type()( size_type(m_.capacity), min_additional_cap, max);
  2094. }
  2095. void buffer_move_or_copy(pointer dst)
  2096. {
  2097. detail::construction_guard<allocator_type> guard(dst, get_allocator_ref());
  2098. buffer_move_or_copy(dst, guard);
  2099. guard.release();
  2100. }
  2101. void buffer_move_or_copy(pointer dst, detail::construction_guard<allocator_type>& guard)
  2102. {
  2103. opt_move_or_copy(begin(), end(), dst, guard);
  2104. destroy_elements(data(), data() + size());
  2105. deallocate_buffer();
  2106. }
  2107. template <typename Guard>
  2108. void opt_move_or_copy(pointer begin, pointer end, pointer dst, Guard& guard)
  2109. {
  2110. // if trivial copy and default allocator, memcpy
  2111. boost::container::uninitialized_move_alloc(get_allocator_ref(), begin, end, dst);
  2112. guard.extend();
  2113. }
  2114. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  2115. template <typename... Args>
  2116. void resize_impl(size_type sz, Args&&... args)
  2117. {
  2118. const size_type old_sz = this->size();
  2119. if (sz > old_sz)
  2120. {
  2121. const size_type n = sz - old_sz;
  2122. if (sz <= m_.capacity)
  2123. {
  2124. //Construct at back
  2125. const size_type bfc = this->back_free_capacity();
  2126. const size_type b = n < bfc ? n : bfc;
  2127. construct_n(m_.buffer + m_.back_idx, b, boost::forward<Args>(args)...);
  2128. m_.set_back_idx(m_.back_idx + b);
  2129. //Construct remaining at front
  2130. const size_type f = n - b;
  2131. construct_n(m_.buffer + m_.front_idx - f, f, boost::forward<Args>(args)...);
  2132. m_.set_front_idx(m_.front_idx - f);
  2133. }
  2134. else
  2135. {
  2136. resize_back_slow_path(sz, n, boost::forward<Args>(args)...);
  2137. }
  2138. }
  2139. else
  2140. {
  2141. const size_type n = old_sz - sz;
  2142. const size_type new_bidx = m_.back_idx - n;
  2143. destroy_elements(m_.buffer + new_bidx, m_.buffer + m_.back_idx);
  2144. m_.set_back_idx(new_bidx);
  2145. }
  2146. }
  2147. template <typename... Args>
  2148. void resize_front_impl(size_type sz , Args&&... args)
  2149. {
  2150. const size_type old_sz = this->size();
  2151. if (sz > old_sz)
  2152. {
  2153. const size_type n = sz - old_sz;
  2154. if (sz <= this->front_capacity())
  2155. {
  2156. construct_n(m_.buffer + m_.front_idx - n, n, boost::forward<Args>(args)...);
  2157. m_.set_front_idx(m_.front_idx - n);
  2158. }
  2159. else
  2160. {
  2161. resize_front_slow_path(sz, n, boost::forward<Args>(args)...);
  2162. }
  2163. }
  2164. else {
  2165. const size_type n = old_sz - sz;
  2166. const size_type new_fidx = m_.front_idx + n;
  2167. destroy_elements(m_.buffer + m_.front_idx, m_.buffer + new_fidx);
  2168. m_.set_front_idx(new_fidx);
  2169. }
  2170. }
  2171. template <typename... Args>
  2172. void resize_front_slow_path(size_type sz, size_type n, Args&&... args)
  2173. {
  2174. const size_type new_capacity = calculate_new_capacity(sz + back_free_capacity());
  2175. pointer new_buffer = allocate(new_capacity);
  2176. allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
  2177. const size_type old_sz = this->size();
  2178. const size_type new_old_elem_index = new_capacity - old_sz;
  2179. const size_type new_elem_index = new_old_elem_index - n;
  2180. detail::construction_guard<allocator_type> guard(new_buffer + new_elem_index, get_allocator_ref());
  2181. guarded_construct_n(new_buffer + new_elem_index, n, guard, boost::forward<Args>(args)...);
  2182. buffer_move_or_copy(new_buffer + new_old_elem_index, guard);
  2183. guard.release();
  2184. new_buffer_guard.release();
  2185. m_.buffer = new_buffer;
  2186. m_.set_capacity(new_capacity);
  2187. m_.set_front_idx(new_elem_index);
  2188. m_.set_back_idx(new_elem_index + old_sz + n);
  2189. }
  2190. template <typename... Args>
  2191. void resize_back_impl(size_type sz, Args&&... args)
  2192. {
  2193. const size_type old_sz = this->size();
  2194. if (sz > old_sz)
  2195. {
  2196. const size_type n = sz - old_sz;
  2197. if (sz <= this->back_capacity())
  2198. {
  2199. construct_n(m_.buffer + m_.back_idx, n, boost::forward<Args>(args)...);
  2200. m_.set_back_idx(m_.back_idx + n);
  2201. }
  2202. else
  2203. {
  2204. resize_back_slow_path(sz, n, boost::forward<Args>(args)...);
  2205. }
  2206. }
  2207. else
  2208. {
  2209. const size_type n = old_sz - sz;
  2210. const size_type new_bidx = m_.back_idx - n;
  2211. destroy_elements(m_.buffer + new_bidx, m_.buffer + m_.back_idx);
  2212. m_.set_back_idx(new_bidx);
  2213. }
  2214. }
  2215. template <typename... Args>
  2216. void resize_back_slow_path(size_type sz, size_type n, Args&&... args)
  2217. {
  2218. const size_type new_capacity = calculate_new_capacity(sz + front_free_capacity());
  2219. pointer new_buffer = allocate(new_capacity);
  2220. allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
  2221. detail::construction_guard<allocator_type> guard(new_buffer + m_.back_idx, get_allocator_ref());
  2222. guarded_construct_n(new_buffer + m_.back_idx, n, guard, boost::forward<Args>(args)...);
  2223. buffer_move_or_copy(new_buffer + m_.front_idx);
  2224. guard.release();
  2225. new_buffer_guard.release();
  2226. m_.buffer = new_buffer;
  2227. m_.set_capacity(new_capacity);
  2228. m_.set_back_idx(m_.back_idx + n);
  2229. }
  2230. #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  2231. #define BOOST_CONTAINER_DEVECTOR_SLOW_PATH(N) \
  2232. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  2233. void resize_front_impl(size_type sz BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  2234. {\
  2235. if (sz > size())\
  2236. {\
  2237. const size_type n = sz - size();\
  2238. if (sz <= front_capacity()){\
  2239. construct_n(m_.buffer + m_.front_idx - n, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  2240. m_.set_front_idx(m_.front_idx - n);\
  2241. }\
  2242. else\
  2243. {\
  2244. resize_front_slow_path(sz, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  2245. }\
  2246. }\
  2247. else {\
  2248. while (this->size() > sz)\
  2249. {\
  2250. this->pop_front();\
  2251. }\
  2252. }\
  2253. }\
  2254. \
  2255. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  2256. void resize_front_slow_path(size_type sz, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  2257. {\
  2258. const size_type new_capacity = calculate_new_capacity(sz + back_free_capacity());\
  2259. pointer new_buffer = allocate(new_capacity);\
  2260. allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());\
  2261. \
  2262. const size_type new_old_elem_index = new_capacity - size();\
  2263. const size_type new_elem_index = new_old_elem_index - n;\
  2264. \
  2265. detail::construction_guard<allocator_type> guard(new_buffer + new_elem_index, get_allocator_ref());\
  2266. guarded_construct_n(new_buffer + new_elem_index, n, guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  2267. \
  2268. buffer_move_or_copy(new_buffer + new_old_elem_index, guard);\
  2269. \
  2270. guard.release();\
  2271. new_buffer_guard.release();\
  2272. m_.buffer = new_buffer;\
  2273. m_.set_capacity(new_capacity);\
  2274. m_.set_back_idx(new_old_elem_index + m_.back_idx - m_.front_idx);\
  2275. m_.set_front_idx(new_elem_index);\
  2276. }\
  2277. \
  2278. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  2279. void resize_back_impl(size_type sz BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  2280. {\
  2281. if (sz > size())\
  2282. {\
  2283. const size_type n = sz - size();\
  2284. \
  2285. if (sz <= back_capacity())\
  2286. {\
  2287. construct_n(m_.buffer + m_.back_idx, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  2288. m_.set_back_idx(m_.back_idx + n);\
  2289. }\
  2290. else\
  2291. {\
  2292. resize_back_slow_path(sz, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  2293. }\
  2294. }\
  2295. else\
  2296. {\
  2297. while (size() > sz)\
  2298. {\
  2299. pop_back();\
  2300. }\
  2301. }\
  2302. }\
  2303. \
  2304. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  2305. void resize_back_slow_path(size_type sz, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  2306. {\
  2307. const size_type new_capacity = calculate_new_capacity(sz + front_free_capacity());\
  2308. pointer new_buffer = allocate(new_capacity);\
  2309. allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());\
  2310. \
  2311. detail::construction_guard<allocator_type> guard(new_buffer + m_.back_idx, get_allocator_ref());\
  2312. guarded_construct_n(new_buffer + m_.back_idx, n, guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  2313. \
  2314. buffer_move_or_copy(new_buffer + m_.front_idx);\
  2315. \
  2316. guard.release();\
  2317. new_buffer_guard.release();\
  2318. \
  2319. m_.buffer = new_buffer;\
  2320. m_.set_capacity(new_capacity);\
  2321. m_.set_back_idx(m_.back_idx + n);\
  2322. }\
  2323. \
  2324. //
  2325. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_SLOW_PATH)
  2326. #undef BOOST_CONTAINER_DEVECTOR_SLOW_PATH
  2327. #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  2328. void reallocate_at(size_type new_capacity, size_type buffer_offset)
  2329. {
  2330. pointer new_buffer = allocate(new_capacity);
  2331. {
  2332. allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
  2333. boost::container::uninitialized_move_alloc(get_allocator_ref(), this->begin(), this->end(), new_buffer + buffer_offset);
  2334. new_buffer_guard.release();
  2335. }
  2336. destroy_elements(m_.buffer + m_.front_idx, m_.buffer + m_.back_idx);
  2337. deallocate_buffer();
  2338. m_.buffer = new_buffer;
  2339. //Safe cast, allocate() will handle stored_size_type overflow
  2340. m_.set_capacity(new_capacity);
  2341. m_.set_back_idx(size_type(m_.back_idx - m_.front_idx) + buffer_offset);
  2342. m_.set_front_idx(buffer_offset);
  2343. BOOST_ASSERT(invariants_ok());
  2344. }
  2345. template <typename ForwardIterator>
  2346. iterator insert_range(const_iterator position, ForwardIterator first, ForwardIterator last)
  2347. {
  2348. BOOST_ASSERT(position >= begin());
  2349. BOOST_ASSERT(position <= end());
  2350. typedef dtl::insert_range_proxy<allocator_type, ForwardIterator> proxy_t;
  2351. size_type const n = boost::container::iterator_udistance(first, last);
  2352. bool prefer_move_back;
  2353. if (BOOST_UNLIKELY(!n)) {
  2354. return begin() + size_type(position - cbegin());
  2355. }
  2356. else if (position == end()) {
  2357. if(back_free_capacity() >= n) // fast path
  2358. {
  2359. iterator r(this->end());
  2360. boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, this->priv_raw_end());
  2361. m_.set_back_idx(m_.back_idx + n);
  2362. return r;
  2363. }
  2364. prefer_move_back = true;
  2365. }
  2366. else if (position == begin()) {
  2367. if(front_free_capacity() >= n) {// secondary fast path
  2368. boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, this->priv_raw_begin() - n);
  2369. m_.set_front_idx(m_.front_idx - n);
  2370. return begin();
  2371. }
  2372. prefer_move_back = false;
  2373. }
  2374. else{
  2375. iterator nonconst_pos = unconst_iterator(position);
  2376. prefer_move_back = should_move_back(position);
  2377. if(prefer_move_back){
  2378. if(back_free_capacity() >= n){
  2379. boost::container::expand_forward_and_insert_nonempty_middle_alloc
  2380. ( get_allocator_ref()
  2381. , boost::movelib::to_raw_pointer(nonconst_pos)
  2382. , this->priv_raw_end()
  2383. , n, proxy_t(first));
  2384. m_.set_back_idx(m_.back_idx + n);
  2385. return nonconst_pos;
  2386. }
  2387. }
  2388. else{
  2389. if (front_free_capacity() >= n){
  2390. boost::container::expand_backward_and_insert_nonempty_middle_alloc
  2391. ( get_allocator_ref()
  2392. , this->priv_raw_begin()
  2393. , boost::movelib::to_raw_pointer(nonconst_pos)
  2394. , n, proxy_t(first));
  2395. m_.set_front_idx(m_.front_idx - n);
  2396. return (nonconst_pos -= n);
  2397. }
  2398. }
  2399. }
  2400. return this->insert_range_slow_path(position, n, proxy_t(first));
  2401. }
  2402. template <class InsertionProxy>
  2403. BOOST_CONTAINER_NOINLINE iterator insert_range_slow_path
  2404. (const_iterator p, const size_type n, const InsertionProxy proxy)
  2405. {
  2406. size_type const back_free_cap = back_free_capacity();
  2407. size_type const front_free_cap = front_free_capacity();
  2408. size_type const free_cap = front_free_cap + back_free_cap;
  2409. size_type const index = size_type(p - cbegin());
  2410. size_type const cap = m_.capacity;
  2411. //Test if enough free memory would be left
  2412. if (free_cap >= n && (free_cap - n) >= cap/devector_min_free_fraction) {
  2413. //Make sure relocation is happening because there was no enough space
  2414. size_type const old_size = this->size();
  2415. BOOST_ASSERT(should_move_back(p) ? (back_free_cap < n) : (front_free_cap < n));
  2416. T* const raw_pos = const_cast<T*>(boost::movelib::to_raw_pointer(p));
  2417. size_type const new_size = old_size + n;
  2418. size_type const new_front_idx = (cap - new_size) / 2u;
  2419. T* const raw_beg = this->priv_raw_begin();
  2420. T* const new_raw_beg = raw_beg - std::ptrdiff_t(m_.front_idx - new_front_idx);
  2421. m_.back_idx = 0u;
  2422. m_.front_idx = 0u;
  2423. boost::container::expand_backward_forward_and_insert_alloc
  2424. (raw_beg, old_size, new_raw_beg, raw_pos, n, proxy, get_allocator_ref());
  2425. m_.set_front_idx(new_front_idx);
  2426. m_.set_back_idx(new_front_idx + new_size);
  2427. }
  2428. else {
  2429. // reallocate
  2430. const size_type new_capacity = calculate_new_capacity(m_.capacity + n);
  2431. pointer new_buffer = allocate(new_capacity);
  2432. // guard allocation
  2433. allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
  2434. size_type const old_size = this->size();
  2435. const size_type new_front_index = (new_capacity - old_size - n) / 2u;
  2436. T* const raw_pos = const_cast<T*>(boost::movelib::to_raw_pointer(p));
  2437. T* const raw_new_start = const_cast<T*>(boost::movelib::to_raw_pointer(new_buffer)) + new_front_index;
  2438. boost::container::uninitialized_move_and_insert_alloc
  2439. (get_allocator_ref(), this->priv_raw_begin(), raw_pos, this->priv_raw_end(), raw_new_start, n, proxy);
  2440. new_buffer_guard.release();
  2441. // cleanup
  2442. destroy_elements(begin(), end());
  2443. deallocate_buffer();
  2444. // rebind members
  2445. m_.set_capacity(new_capacity);
  2446. m_.buffer = new_buffer;
  2447. m_.set_back_idx(new_front_index + old_size + n);
  2448. m_.set_front_idx(new_front_index);
  2449. }
  2450. return begin() + index;
  2451. }
  2452. template <typename Iterator>
  2453. void construct_from_range(Iterator begin, Iterator end)
  2454. {
  2455. allocation_guard buffer_guard(m_.buffer, m_.capacity, get_allocator_ref());
  2456. boost::container::uninitialized_copy_alloc(get_allocator_ref(), begin, end, m_.buffer);
  2457. buffer_guard.release();
  2458. }
  2459. template <typename ForwardIterator>
  2460. void allocate_and_copy_range(ForwardIterator first, ForwardIterator last)
  2461. {
  2462. size_type n = boost::container::iterator_udistance(first, last);
  2463. pointer new_buffer = n ? allocate(n) : pointer();
  2464. allocation_guard new_buffer_guard(new_buffer, n, get_allocator_ref());
  2465. boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, new_buffer);
  2466. destroy_elements(begin(), end());
  2467. deallocate_buffer();
  2468. m_.set_capacity(n);
  2469. m_.buffer = new_buffer;
  2470. m_.front_idx = 0;
  2471. m_.set_back_idx(n);
  2472. new_buffer_guard.release();
  2473. }
  2474. static void swap_big_big(devector& a, devector& b) BOOST_NOEXCEPT
  2475. {
  2476. boost::adl_move_swap(a.m_.capacity, b.m_.capacity);
  2477. boost::adl_move_swap(a.m_.buffer, b.m_.buffer);
  2478. }
  2479. template <typename ForwardIterator>
  2480. void overwrite_buffer_impl(ForwardIterator first, ForwardIterator last, dtl::true_)
  2481. {
  2482. const size_type n = boost::container::iterator_udistance(first, last);
  2483. BOOST_ASSERT(m_.capacity >= n);
  2484. boost::container::uninitialized_copy_alloc_n
  2485. ( get_allocator_ref(), first
  2486. , n, boost::movelib::to_raw_pointer(m_.buffer));
  2487. m_.front_idx = 0;
  2488. m_.set_back_idx(n);
  2489. }
  2490. template <typename InputIterator>
  2491. InputIterator overwrite_buffer_impl(InputIterator first, InputIterator last, dtl::false_)
  2492. {
  2493. pointer pos = m_.buffer;
  2494. detail::construction_guard<allocator_type> front_guard(pos, get_allocator_ref());
  2495. while (first != last && pos != begin()) {
  2496. this->alloc_construct(pos++, *first++);
  2497. front_guard.extend();
  2498. }
  2499. while (first != last && pos != end()) {
  2500. *pos++ = *first++;
  2501. }
  2502. detail::construction_guard<allocator_type> back_guard(pos, get_allocator_ref());
  2503. iterator capacity_end = m_.buffer + m_.capacity;
  2504. while (first != last && pos != capacity_end) {
  2505. this->alloc_construct(pos++, *first++);
  2506. back_guard.extend();
  2507. }
  2508. pointer destroy_after = dtl::min_value(dtl::max_value(begin(), pos), end());
  2509. destroy_elements(destroy_after, end());
  2510. front_guard.release();
  2511. back_guard.release();
  2512. m_.front_idx = 0;
  2513. m_.set_back_idx(pos_to_index(pos));
  2514. return first;
  2515. }
  2516. template <typename ForwardIterator>
  2517. BOOST_CONTAINER_FORCEINLINE void overwrite_buffer(ForwardIterator first, ForwardIterator last)
  2518. {
  2519. this->overwrite_buffer_impl(first, last,
  2520. dtl::bool_<dtl::is_trivially_destructible<T>::value>());
  2521. }
  2522. bool invariants_ok()
  2523. {
  2524. return (! m_.capacity || m_.buffer )
  2525. && m_.front_idx <= m_.back_idx
  2526. && m_.back_idx <= m_.capacity;
  2527. }
  2528. struct impl : allocator_type
  2529. {
  2530. BOOST_MOVABLE_BUT_NOT_COPYABLE(impl)
  2531. public:
  2532. allocator_type &get_al()
  2533. { return *this; }
  2534. static pointer do_allocate(allocator_type &a, size_type cap)
  2535. {
  2536. if (cap) {
  2537. //First detect overflow on smaller stored_size_types
  2538. if (cap > stored_size_type(-1)){
  2539. boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
  2540. }
  2541. return allocator_traits_type::allocate(a, cap);
  2542. }
  2543. else {
  2544. return pointer();
  2545. }
  2546. }
  2547. impl()
  2548. : allocator_type(), buffer(), front_idx(), back_idx(), capacity()
  2549. #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2550. , capacity_alloc_count(0)
  2551. #endif
  2552. {}
  2553. explicit impl(const allocator_type &a)
  2554. : allocator_type(a), buffer(), front_idx(), back_idx(), capacity()
  2555. #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2556. , capacity_alloc_count(0)
  2557. #endif
  2558. {}
  2559. impl(reserve_uninitialized_t, const allocator_type& a, size_type c)
  2560. : allocator_type(a), buffer(do_allocate(get_al(), c) )
  2561. //static cast sizes, as the allocation function will take care of overflows
  2562. , front_idx(static_cast<stored_size_type>(0u))
  2563. , back_idx(static_cast<stored_size_type>(c))
  2564. , capacity(static_cast<stored_size_type>(c))
  2565. #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2566. , capacity_alloc_count(size_type(buffer != pointer()))
  2567. #endif
  2568. {}
  2569. impl(reserve_only_tag_t, const allocator_type &a, size_type const ffc, size_type const bfc)
  2570. : allocator_type(a), buffer(do_allocate(get_al(), ffc+bfc) )
  2571. //static cast sizes, as the allocation function will take care of overflows
  2572. , front_idx(static_cast<stored_size_type>(ffc))
  2573. , back_idx(static_cast<stored_size_type>(ffc))
  2574. , capacity(static_cast<stored_size_type>(ffc + bfc))
  2575. #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2576. , capacity_alloc_count(size_type(buffer != pointer()))
  2577. #endif
  2578. {}
  2579. impl(reserve_only_tag_t, const allocator_type &a, size_type const c)
  2580. : allocator_type(a), buffer(do_allocate(get_al(), c) )
  2581. //static cast sizes, as the allocation function will take care of overflows
  2582. , front_idx(static_cast<stored_size_type>(c/2u))
  2583. , back_idx(static_cast<stored_size_type>(c/2u))
  2584. , capacity(static_cast<stored_size_type>(c))
  2585. #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2586. , capacity_alloc_count(size_type(buffer != pointer()))
  2587. #endif
  2588. {}
  2589. impl(review_implementation_t, const allocator_type &a, pointer p, size_type fi, size_type bi, size_type c)
  2590. : allocator_type(a), buffer(p)
  2591. //static cast sizes, as the allocation function will take care of overflows
  2592. , front_idx(static_cast<stored_size_type>(fi))
  2593. , back_idx(static_cast<stored_size_type>(bi))
  2594. , capacity(static_cast<stored_size_type>(c))
  2595. #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2596. , capacity_alloc_count(0)
  2597. #endif
  2598. {}
  2599. impl(BOOST_RV_REF(impl) m)
  2600. : allocator_type(BOOST_MOVE_BASE(allocator_type, m))
  2601. , buffer(static_cast<impl&>(m).buffer)
  2602. , front_idx(static_cast<impl&>(m).front_idx)
  2603. , back_idx(static_cast<impl&>(m).back_idx)
  2604. , capacity(static_cast<impl&>(m).capacity)
  2605. #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2606. , capacity_alloc_count(0)
  2607. #endif
  2608. {
  2609. impl &i = static_cast<impl&>(m);
  2610. // buffer is already acquired, reset rhs
  2611. i.capacity = 0u;
  2612. i.buffer = pointer();
  2613. i.front_idx = 0;
  2614. i.back_idx = 0;
  2615. }
  2616. BOOST_CONTAINER_FORCEINLINE void set_back_idx(size_type bi)
  2617. {
  2618. back_idx = static_cast<stored_size_type>(bi);
  2619. }
  2620. BOOST_CONTAINER_FORCEINLINE void set_front_idx(size_type fi)
  2621. {
  2622. front_idx = static_cast<stored_size_type>(fi);
  2623. }
  2624. BOOST_CONTAINER_FORCEINLINE void set_capacity(size_type c)
  2625. {
  2626. capacity = static_cast<stored_size_type>(c);
  2627. }
  2628. pointer buffer;
  2629. stored_size_type front_idx;
  2630. stored_size_type back_idx;
  2631. stored_size_type capacity;
  2632. #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2633. size_type capacity_alloc_count;
  2634. #endif
  2635. } m_;
  2636. #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2637. public:
  2638. void reset_alloc_stats()
  2639. {
  2640. m_.capacity_alloc_count = 0;
  2641. }
  2642. size_type get_alloc_count() const
  2643. {
  2644. return m_.capacity_alloc_count;
  2645. }
  2646. #endif // ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
  2647. #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  2648. };
  2649. }} // namespace boost::container
  2650. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  2651. namespace boost {
  2652. //!has_trivial_destructor_after_move<> == true_type
  2653. //!specialization for optimizations
  2654. template <class T, class Allocator, class Options>
  2655. struct has_trivial_destructor_after_move<boost::container::devector<T, Allocator, Options> >
  2656. {
  2657. typedef typename boost::container::devector<T, Allocator, Options>::allocator_type allocator_type;
  2658. typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
  2659. static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
  2660. ::boost::has_trivial_destructor_after_move<pointer>::value;
  2661. };
  2662. }
  2663. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  2664. #include <boost/container/detail/config_end.hpp>
  2665. #endif // BOOST_CONTAINER_DEVECTOR_HPP