flat_tree.hpp 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2015. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. ////////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_CONTAINER_FLAT_TREE_HPP
  11. #define BOOST_CONTAINER_FLAT_TREE_HPP
  12. #ifndef BOOST_CONFIG_HPP
  13. # include <boost/config.hpp>
  14. #endif
  15. #if defined(BOOST_HAS_PRAGMA_ONCE)
  16. # pragma once
  17. #endif
  18. #include <boost/container/detail/config_begin.hpp>
  19. #include <boost/container/detail/workaround.hpp>
  20. #include <boost/container/container_fwd.hpp>
  21. #include <boost/move/utility_core.hpp>
  22. #include <boost/container/vector.hpp>
  23. #include <boost/container/allocator_traits.hpp>
  24. #include <boost/container/detail/value_init.hpp>
  25. #include <boost/container/detail/destroyers.hpp>
  26. #include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
  27. #include <boost/container/detail/iterator.hpp>
  28. #include <boost/container/detail/is_sorted.hpp>
  29. #include <boost/container/detail/type_traits.hpp>
  30. #include <boost/container/detail/iterators.hpp>
  31. #include <boost/container/detail/mpl.hpp>
  32. #include <boost/container/detail/is_contiguous_container.hpp>
  33. #include <boost/container/detail/is_container.hpp>
  34. #include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
  35. #include <boost/move/iterator.hpp>
  36. #include <boost/move/adl_move_swap.hpp>
  37. #include <boost/move/detail/iterator_to_raw_pointer.hpp>
  38. #include <boost/move/detail/force_ptr.hpp>
  39. #include <boost/move/detail/launder.hpp>
  40. #include <boost/move/algo/adaptive_sort.hpp>
  41. #include <boost/move/algo/detail/pdqsort.hpp>
  42. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  43. #include <boost/move/detail/fwd_macros.hpp>
  44. #endif
  45. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  46. #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
  47. #pragma GCC diagnostic push
  48. #pragma GCC diagnostic ignored "-Wunused-result"
  49. #endif
  50. //merge_unique
  51. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME merge_unique
  52. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
  53. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
  54. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
  55. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
  56. #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
  57. //merge_equal
  58. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME merge
  59. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
  60. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
  61. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
  62. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
  63. #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
  64. //index_of
  65. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME index_of
  66. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
  67. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
  68. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
  69. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
  70. #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
  71. //nth
  72. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME nth
  73. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
  74. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
  75. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
  76. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
  77. #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
  78. //reserve
  79. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME reserve
  80. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
  81. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
  82. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
  83. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
  84. #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
  85. //capacity
  86. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME capacity
  87. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
  88. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
  89. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
  90. #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
  91. #include <boost/intrusive/detail/has_member_function_callable_with.hpp>
  92. #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
  93. #pragma GCC diagnostic pop
  94. #endif
  95. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  96. namespace boost {
  97. namespace container {
  98. namespace dtl {
  99. ///////////////////////////////////////
  100. //
  101. // Helper functions to merge elements
  102. //
  103. ///////////////////////////////////////
  104. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(stored_allocator_type)
  105. ///////////////////////////////////////
  106. //
  107. // flat_tree_container_inplace_merge
  108. //
  109. ///////////////////////////////////////
  110. template<class SequenceContainer, class Compare>
  111. inline void flat_tree_container_inplace_merge //is_contiguous_container == true
  112. (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::true_)
  113. {
  114. typedef typename SequenceContainer::value_type value_type;
  115. value_type *const braw = boost::movelib::to_raw_pointer(dest.data());
  116. value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
  117. //Don't use iterator_to_raw_pointer for end as debug iterators can assert when
  118. //"operator ->" is used with the end iterator
  119. value_type *const eraw = braw + dest.size();
  120. boost::movelib::adaptive_merge
  121. (braw, iraw, eraw, comp, eraw, back_free_capacity<SequenceContainer>::get(dest));
  122. }
  123. template<class SequenceContainer, class Compare>
  124. inline void flat_tree_container_inplace_merge //is_contiguous_container == false
  125. (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::false_)
  126. {
  127. boost::movelib::adaptive_merge(dest.begin(), it, dest.end(), comp);
  128. }
  129. ///////////////////////////////////////
  130. //
  131. // flat_tree_container_inplace_sort_ending
  132. //
  133. ///////////////////////////////////////
  134. template<class SequenceContainer, class Compare>
  135. inline void flat_tree_container_inplace_sort_ending //is_contiguous_container == true
  136. (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::true_)
  137. {
  138. typedef typename SequenceContainer::value_type value_type;
  139. value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
  140. //Don't use iterator_to_raw_pointer for end as debug iterators can assert when
  141. //"operator ->" is used with the end iterator
  142. value_type* const eraw = boost::movelib::to_raw_pointer(dest.data()) + dest.size();
  143. boost::movelib::adaptive_sort
  144. (iraw, eraw, comp, eraw, back_free_capacity<SequenceContainer>::get(dest));
  145. }
  146. template<class SequenceContainer, class Compare>
  147. inline void flat_tree_container_inplace_sort_ending //is_contiguous_container == false
  148. (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::false_)
  149. {
  150. boost::movelib::adaptive_sort(it, dest.end(), comp);
  151. }
  152. ///////////////////////////////////////
  153. //
  154. // flat_tree_merge
  155. //
  156. ///////////////////////////////////////
  157. template<class SequenceContainer, class Iterator, class Compare>
  158. inline void flat_tree_merge_equal
  159. (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
  160. {
  161. dest.merge(first, last, comp);
  162. }
  163. template<class SequenceContainer, class Iterator, class Compare>
  164. inline void flat_tree_merge_equal //has_merge_unique == false
  165. (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
  166. {
  167. if(first != last) {
  168. typedef typename SequenceContainer::iterator iterator;
  169. iterator const it = dest.insert( dest.end(), first, last );
  170. dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
  171. (flat_tree_container_inplace_merge)(dest, it, comp, contiguous_tag);
  172. }
  173. }
  174. ///////////////////////////////////////
  175. //
  176. // flat_tree_merge_unique
  177. //
  178. ///////////////////////////////////////
  179. template<class SequenceContainer, class Iterator, class Compare>
  180. inline void flat_tree_merge_unique //has_merge_unique == true
  181. (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
  182. {
  183. dest.merge_unique(first, last, comp);
  184. }
  185. template<class SequenceContainer, class Iterator, class Compare>
  186. inline void flat_tree_merge_unique //has_merge_unique == false
  187. (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
  188. {
  189. if (first != last) {
  190. typedef typename SequenceContainer::iterator iterator;
  191. typedef typename SequenceContainer::size_type size_type;
  192. typedef typename SequenceContainer::difference_type difference_type;
  193. size_type const old_sz = dest.size();
  194. iterator const first_new = dest.insert(dest.cend(), first, last );
  195. iterator e = boost::movelib::inplace_set_unique_difference(first_new, dest.end(), dest.begin(), first_new, comp);
  196. dest.erase(e, dest.end());
  197. dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
  198. (flat_tree_container_inplace_merge)(dest, dest.begin() + difference_type(old_sz), comp, contiguous_tag);
  199. }
  200. }
  201. ///////////////////////////////////////
  202. //
  203. // flat_tree_index_of
  204. //
  205. ///////////////////////////////////////
  206. template<class SequenceContainer, class Iterator>
  207. inline typename SequenceContainer::size_type
  208. flat_tree_index_of // has_index_of == true
  209. (SequenceContainer& cont, Iterator p, dtl::true_)
  210. {
  211. return cont.index_of(p);
  212. }
  213. template<class SequenceContainer, class Iterator>
  214. inline typename SequenceContainer::size_type
  215. flat_tree_index_of // has_index_of == false
  216. (SequenceContainer& cont, Iterator p, dtl::false_)
  217. {
  218. typedef typename SequenceContainer::size_type size_type;
  219. return static_cast<size_type>(p - cont.begin());
  220. }
  221. ///////////////////////////////////////
  222. //
  223. // flat_tree_nth
  224. //
  225. ///////////////////////////////////////
  226. template<class Iterator, class SequenceContainer>
  227. inline Iterator
  228. flat_tree_nth // has_nth == true
  229. (SequenceContainer& cont, typename SequenceContainer::size_type n, dtl::true_)
  230. {
  231. return cont.nth(n);
  232. }
  233. template<class Iterator, class SequenceContainer>
  234. inline Iterator
  235. flat_tree_nth // has_nth == false
  236. (SequenceContainer& cont, typename SequenceContainer::size_type n, dtl::false_)
  237. {
  238. return cont.begin()+ typename SequenceContainer::difference_type(n);
  239. }
  240. ///////////////////////////////////////
  241. //
  242. // flat_tree_get_stored_allocator
  243. //
  244. ///////////////////////////////////////
  245. template<class SequenceContainer>
  246. inline typename SequenceContainer::stored_allocator_type &
  247. flat_tree_get_stored_allocator // has_get_stored_allocator == true
  248. (SequenceContainer& cont, dtl::true_)
  249. {
  250. return cont.get_stored_allocator();
  251. }
  252. template<class SequenceContainer>
  253. inline const typename SequenceContainer::stored_allocator_type &
  254. flat_tree_get_stored_allocator // has_get_stored_allocator == true
  255. (const SequenceContainer& cont, dtl::true_)
  256. {
  257. return cont.get_stored_allocator();
  258. }
  259. template<class SequenceContainer>
  260. inline typename SequenceContainer::allocator_type
  261. flat_tree_get_stored_allocator // has_get_stored_allocator == false
  262. (SequenceContainer& cont, dtl::false_)
  263. {
  264. return cont.get_allocator();
  265. }
  266. ///////////////////////////////////////
  267. //
  268. // flat_tree_adopt_sequence_equal
  269. //
  270. ///////////////////////////////////////
  271. template<class SequenceContainer, class Compare>
  272. void flat_tree_sort_contiguous_to_adopt // is_contiguous_container == true
  273. (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp)
  274. {
  275. if(tseq.capacity() >= (seq.capacity() - seq.size())) {
  276. tseq.clear();
  277. boost::movelib::adaptive_sort
  278. (boost::movelib::iterator_to_raw_pointer(seq.begin())
  279. , boost::movelib::iterator_to_raw_pointer(seq.end())
  280. , comp
  281. , boost::movelib::iterator_to_raw_pointer(tseq.begin())
  282. , tseq.capacity());
  283. }
  284. else{
  285. boost::movelib::adaptive_sort
  286. (boost::movelib::iterator_to_raw_pointer(seq.begin())
  287. , boost::movelib::iterator_to_raw_pointer(seq.end())
  288. , comp
  289. , boost::movelib::iterator_to_raw_pointer(seq.end())
  290. , seq.capacity() - seq.size());
  291. }
  292. }
  293. template<class SequenceContainer, class Compare>
  294. inline void flat_tree_adopt_sequence_equal // is_contiguous_container == true
  295. (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
  296. {
  297. flat_tree_sort_contiguous_to_adopt(tseq, boost::move(seq), comp);
  298. tseq = boost::move(seq);
  299. }
  300. template<class SequenceContainer, class Compare>
  301. inline void flat_tree_adopt_sequence_equal // is_contiguous_container == false
  302. (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
  303. {
  304. boost::movelib::adaptive_sort(seq.begin(), seq.end(), comp);
  305. tseq = boost::move(seq);
  306. }
  307. ///////////////////////////////////////
  308. //
  309. // flat_tree_adopt_sequence_unique
  310. //
  311. ///////////////////////////////////////
  312. template<class SequenceContainer, class Compare>
  313. void flat_tree_adopt_sequence_unique// is_contiguous_container == true
  314. (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
  315. {
  316. boost::movelib::pdqsort
  317. ( boost::movelib::iterator_to_raw_pointer(seq.begin())
  318. , boost::movelib::iterator_to_raw_pointer(seq.end())
  319. , comp);
  320. seq.erase(boost::movelib::unique
  321. (seq.begin(), seq.end(), boost::movelib::negate<Compare>(comp)), seq.cend());
  322. tseq = boost::move(seq);
  323. }
  324. template<class SequenceContainer, class Compare>
  325. void flat_tree_adopt_sequence_unique// is_contiguous_container == false
  326. (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
  327. {
  328. boost::movelib::pdqsort(seq.begin(), seq.end(), comp);
  329. seq.erase(boost::movelib::unique
  330. (seq.begin(), seq.end(), boost::movelib::negate<Compare>(comp)), seq.cend());
  331. tseq = boost::move(seq);
  332. }
  333. ///////////////////////////////////////
  334. //
  335. // flat_tree_reserve
  336. //
  337. ///////////////////////////////////////
  338. template<class SequenceContainer>
  339. inline void // has_reserve == true
  340. flat_tree_reserve(SequenceContainer &tseq, typename SequenceContainer::size_type cap, dtl::true_)
  341. {
  342. tseq.reserve(cap);
  343. }
  344. template<class SequenceContainer>
  345. inline void // has_reserve == false
  346. flat_tree_reserve(SequenceContainer &, typename SequenceContainer::size_type, dtl::false_)
  347. {
  348. }
  349. ///////////////////////////////////////
  350. //
  351. // flat_tree_capacity
  352. //
  353. ///////////////////////////////////////
  354. template<class SequenceContainer> // has_capacity == true
  355. inline typename SequenceContainer::size_type
  356. flat_tree_capacity(const SequenceContainer &tseq, dtl::true_)
  357. {
  358. return tseq.capacity();
  359. }
  360. template<class SequenceContainer> // has_capacity == false
  361. inline typename SequenceContainer::size_type
  362. flat_tree_capacity(const SequenceContainer &tseq, dtl::false_)
  363. {
  364. return tseq.size();
  365. }
  366. ///////////////////////////////////////
  367. //
  368. // flat_tree_value_compare
  369. //
  370. ///////////////////////////////////////
  371. template<class Compare, class Value, class KeyOfValue>
  372. class flat_tree_value_compare
  373. : private Compare
  374. {
  375. typedef Value first_argument_type;
  376. typedef Value second_argument_type;
  377. typedef bool return_type;
  378. public:
  379. inline flat_tree_value_compare()
  380. : Compare()
  381. {}
  382. inline flat_tree_value_compare(const Compare &pred)
  383. : Compare(pred)
  384. {}
  385. inline bool operator()(const Value& lhs, const Value& rhs) const
  386. {
  387. KeyOfValue key_extract;
  388. return Compare::operator()(key_extract(lhs), key_extract(rhs));
  389. }
  390. inline const Compare &get_comp() const
  391. { return *this; }
  392. inline Compare &get_comp()
  393. { return *this; }
  394. };
  395. ///////////////////////////////////////
  396. //
  397. // select_container_type
  398. //
  399. ///////////////////////////////////////
  400. template < class Value, class AllocatorOrContainer
  401. , bool = boost::container::dtl::is_container<AllocatorOrContainer>::value
  402. >
  403. struct select_container_type
  404. {
  405. typedef AllocatorOrContainer type;
  406. };
  407. template <class Value, class AllocatorOrContainer>
  408. struct select_container_type<Value, AllocatorOrContainer, false>
  409. {
  410. typedef boost::container::vector<Value, typename real_allocator<Value, AllocatorOrContainer>::type> type;
  411. };
  412. ///////////////////////////////////////
  413. //
  414. // flat_tree
  415. //
  416. ///////////////////////////////////////
  417. template <class Value, class KeyOfValue,
  418. class Compare, class AllocatorOrContainer>
  419. class flat_tree
  420. {
  421. public:
  422. typedef typename select_container_type<Value, AllocatorOrContainer>::type container_type;
  423. typedef container_type sequence_type; //For backwards compatibility
  424. private:
  425. typedef typename container_type::allocator_type allocator_t;
  426. typedef allocator_traits<allocator_t> allocator_traits_type;
  427. public:
  428. typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare;
  429. private:
  430. struct Data
  431. //Inherit from value_compare to do EBO
  432. : public value_compare
  433. {
  434. BOOST_COPYABLE_AND_MOVABLE(Data)
  435. public:
  436. inline Data()
  437. : value_compare(), m_seq()
  438. {}
  439. inline explicit Data(const allocator_t &alloc)
  440. : value_compare(), m_seq(alloc)
  441. {}
  442. inline explicit Data(const Compare &comp)
  443. : value_compare(comp), m_seq()
  444. {}
  445. inline Data(const Compare &comp, const allocator_t &alloc)
  446. : value_compare(comp), m_seq(alloc)
  447. {}
  448. inline explicit Data(const Data &d)
  449. : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq)
  450. {}
  451. inline Data(BOOST_RV_REF(Data) d)
  452. : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq))
  453. {}
  454. inline Data(const Data &d, const allocator_t &a)
  455. : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq, a)
  456. {}
  457. inline Data(BOOST_RV_REF(Data) d, const allocator_t &a)
  458. : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq), a)
  459. {}
  460. Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d)
  461. {
  462. this->value_compare::operator=(d);
  463. m_seq = d.m_seq;
  464. return *this;
  465. }
  466. Data& operator=(BOOST_RV_REF(Data) d)
  467. {
  468. this->value_compare::operator=(boost::move(static_cast<value_compare &>(d)));
  469. m_seq = boost::move(d.m_seq);
  470. return *this;
  471. }
  472. void swap(Data &d)
  473. {
  474. value_compare& mycomp = *this, & othercomp = d;
  475. boost::adl_move_swap(mycomp, othercomp);
  476. this->m_seq.swap(d.m_seq);
  477. }
  478. container_type m_seq;
  479. };
  480. Data m_data;
  481. BOOST_COPYABLE_AND_MOVABLE(flat_tree)
  482. public:
  483. typedef typename container_type::value_type value_type;
  484. typedef typename container_type::pointer pointer;
  485. typedef typename container_type::const_pointer const_pointer;
  486. typedef typename container_type::reference reference;
  487. typedef typename container_type::const_reference const_reference;
  488. typedef typename KeyOfValue::type key_type;
  489. typedef Compare key_compare;
  490. typedef typename container_type::allocator_type allocator_type;
  491. typedef typename container_type::size_type size_type;
  492. typedef typename container_type::difference_type difference_type;
  493. typedef typename container_type::iterator iterator;
  494. typedef typename container_type::const_iterator const_iterator;
  495. typedef typename container_type::reverse_iterator reverse_iterator;
  496. typedef typename container_type::const_reverse_iterator const_reverse_iterator;
  497. //!Standard extension
  498. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  499. (boost::container::dtl::, container_type
  500. ,stored_allocator_type, allocator_type) stored_allocator_type;
  501. BOOST_STATIC_CONSTEXPR bool has_stored_allocator_type =
  502. BOOST_INTRUSIVE_HAS_TYPE(boost::container::dtl::, container_type, stored_allocator_type);
  503. private:
  504. typedef allocator_traits<stored_allocator_type> stored_allocator_traits;
  505. public:
  506. typedef typename dtl::if_c
  507. <has_stored_allocator_type, const stored_allocator_type &, allocator_type>::type get_stored_allocator_const_return_t;
  508. typedef typename dtl::if_c
  509. <has_stored_allocator_type, stored_allocator_type &, allocator_type>::type get_stored_allocator_noconst_return_t;
  510. inline flat_tree()
  511. : m_data()
  512. { }
  513. inline explicit flat_tree(const Compare& comp)
  514. : m_data(comp)
  515. { }
  516. inline explicit flat_tree(const allocator_type& a)
  517. : m_data(a)
  518. { }
  519. inline flat_tree(const Compare& comp, const allocator_type& a)
  520. : m_data(comp, a)
  521. { }
  522. inline flat_tree(const flat_tree& x)
  523. : m_data(x.m_data)
  524. { }
  525. inline flat_tree(BOOST_RV_REF(flat_tree) x)
  526. BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
  527. : m_data(boost::move(x.m_data))
  528. { }
  529. inline flat_tree(const flat_tree& x, const allocator_type &a)
  530. : m_data(x.m_data, a)
  531. { }
  532. inline flat_tree(BOOST_RV_REF(flat_tree) x, const allocator_type &a)
  533. : m_data(boost::move(x.m_data), a)
  534. { }
  535. template <class InputIterator>
  536. inline
  537. flat_tree( ordered_range_t, InputIterator first, InputIterator last)
  538. : m_data()
  539. {
  540. this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
  541. BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
  542. }
  543. template <class InputIterator>
  544. inline
  545. flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
  546. : m_data(comp)
  547. {
  548. this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
  549. BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
  550. }
  551. template <class InputIterator>
  552. inline
  553. flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
  554. : m_data(comp, a)
  555. {
  556. this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
  557. BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
  558. }
  559. template <class InputIterator>
  560. inline
  561. flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last)
  562. : m_data()
  563. {
  564. this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
  565. BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
  566. }
  567. template <class InputIterator>
  568. inline
  569. flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
  570. : m_data(comp)
  571. {
  572. this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
  573. BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
  574. }
  575. template <class InputIterator>
  576. inline
  577. flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
  578. : m_data(comp, a)
  579. {
  580. this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
  581. BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
  582. }
  583. template <class InputIterator>
  584. inline
  585. flat_tree( bool unique_insertion, InputIterator first, InputIterator last)
  586. : m_data()
  587. {
  588. this->priv_range_insertion_construct(unique_insertion, first, last);
  589. }
  590. template <class InputIterator>
  591. inline
  592. flat_tree( bool unique_insertion, InputIterator first, InputIterator last
  593. , const Compare& comp)
  594. : m_data(comp)
  595. {
  596. this->priv_range_insertion_construct(unique_insertion, first, last);
  597. }
  598. template <class InputIterator>
  599. inline
  600. flat_tree( bool unique_insertion, InputIterator first, InputIterator last
  601. , const allocator_type& a)
  602. : m_data(a)
  603. {
  604. this->priv_range_insertion_construct(unique_insertion, first, last);
  605. }
  606. template <class InputIterator>
  607. inline
  608. flat_tree( bool unique_insertion, InputIterator first, InputIterator last
  609. , const Compare& comp, const allocator_type& a)
  610. : m_data(comp, a)
  611. {
  612. this->priv_range_insertion_construct(unique_insertion, first, last);
  613. }
  614. inline ~flat_tree()
  615. {}
  616. inline flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x)
  617. { m_data = x.m_data; return *this; }
  618. inline flat_tree& operator=(BOOST_RV_REF(flat_tree) x)
  619. BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
  620. allocator_traits_type::is_always_equal::value) &&
  621. boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
  622. { m_data = boost::move(x.m_data); return *this; }
  623. inline const value_compare &priv_value_comp() const
  624. { return static_cast<const value_compare &>(this->m_data); }
  625. inline value_compare &priv_value_comp()
  626. { return static_cast<value_compare &>(this->m_data); }
  627. inline const key_compare &priv_key_comp() const
  628. { return this->priv_value_comp().get_comp(); }
  629. inline key_compare &priv_key_comp()
  630. { return this->priv_value_comp().get_comp(); }
  631. struct insert_commit_data
  632. {
  633. const_iterator position;
  634. };
  635. public:
  636. // accessors:
  637. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  638. Compare key_comp() const
  639. { return this->m_data.get_comp(); }
  640. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  641. value_compare value_comp() const
  642. { return this->m_data; }
  643. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  644. allocator_type get_allocator() const
  645. { return this->m_data.m_seq.get_allocator(); }
  646. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  647. get_stored_allocator_const_return_t get_stored_allocator() const
  648. {
  649. return flat_tree_get_stored_allocator(this->m_data.m_seq, dtl::bool_<has_stored_allocator_type>());
  650. }
  651. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  652. get_stored_allocator_noconst_return_t get_stored_allocator()
  653. {
  654. return flat_tree_get_stored_allocator(this->m_data.m_seq, dtl::bool_<has_stored_allocator_type>());
  655. }
  656. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  657. iterator begin()
  658. { return this->m_data.m_seq.begin(); }
  659. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  660. const_iterator begin() const
  661. { return this->cbegin(); }
  662. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  663. const_iterator cbegin() const
  664. { return this->m_data.m_seq.begin(); }
  665. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  666. iterator end()
  667. { return this->m_data.m_seq.end(); }
  668. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  669. const_iterator end() const
  670. { return this->cend(); }
  671. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  672. const_iterator cend() const
  673. { return this->m_data.m_seq.end(); }
  674. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  675. reverse_iterator rbegin()
  676. { return reverse_iterator(this->end()); }
  677. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  678. const_reverse_iterator rbegin() const
  679. { return this->crbegin(); }
  680. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  681. const_reverse_iterator crbegin() const
  682. { return const_reverse_iterator(this->cend()); }
  683. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  684. reverse_iterator rend()
  685. { return reverse_iterator(this->begin()); }
  686. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  687. const_reverse_iterator rend() const
  688. { return this->crend(); }
  689. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  690. const_reverse_iterator crend() const
  691. { return const_reverse_iterator(this->cbegin()); }
  692. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  693. bool empty() const
  694. { return this->m_data.m_seq.empty(); }
  695. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  696. size_type size() const
  697. { return this->m_data.m_seq.size(); }
  698. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  699. size_type max_size() const
  700. { return this->m_data.m_seq.max_size(); }
  701. inline void swap(flat_tree& other)
  702. BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
  703. && boost::container::dtl::is_nothrow_swappable<Compare>::value )
  704. { this->m_data.swap(other.m_data); }
  705. public:
  706. // insert/erase
  707. std::pair<iterator,bool> insert_unique(const value_type& val)
  708. {
  709. std::pair<iterator,bool> ret;
  710. insert_commit_data data;
  711. ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
  712. ret.first = ret.second ? this->priv_insert_commit(data, val)
  713. : this->begin() + (data.position - this->cbegin());
  714. //: iterator(vector_iterator_get_ptr(data.position));
  715. return ret;
  716. }
  717. std::pair<iterator,bool> insert_unique(BOOST_RV_REF(value_type) val)
  718. {
  719. std::pair<iterator,bool> ret;
  720. insert_commit_data data;
  721. ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
  722. ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val))
  723. : this->begin() + (data.position - this->cbegin());
  724. //: iterator(vector_iterator_get_ptr(data.position));
  725. return ret;
  726. }
  727. iterator insert_equal(const value_type& val)
  728. {
  729. iterator i = this->upper_bound(KeyOfValue()(val));
  730. i = this->m_data.m_seq.insert(i, val);
  731. return i;
  732. }
  733. iterator insert_equal(BOOST_RV_REF(value_type) mval)
  734. {
  735. iterator i = this->upper_bound(KeyOfValue()(mval));
  736. i = this->m_data.m_seq.insert(i, boost::move(mval));
  737. return i;
  738. }
  739. iterator insert_unique(const_iterator hint, const value_type& val)
  740. {
  741. BOOST_ASSERT(this->priv_in_range_or_end(hint));
  742. insert_commit_data data;
  743. return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
  744. ? this->priv_insert_commit(data, val)
  745. : this->begin() + (data.position - this->cbegin());
  746. //: iterator(vector_iterator_get_ptr(data.position));
  747. }
  748. iterator insert_unique(const_iterator hint, BOOST_RV_REF(value_type) val)
  749. {
  750. BOOST_ASSERT(this->priv_in_range_or_end(hint));
  751. insert_commit_data data;
  752. return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
  753. ? this->priv_insert_commit(data, boost::move(val))
  754. : this->begin() + (data.position - this->cbegin());
  755. //: iterator(vector_iterator_get_ptr(data.position));
  756. }
  757. iterator insert_equal(const_iterator hint, const value_type& val)
  758. {
  759. BOOST_ASSERT(this->priv_in_range_or_end(hint));
  760. insert_commit_data data;
  761. this->priv_insert_equal_prepare(hint, val, data);
  762. return this->priv_insert_commit(data, val);
  763. }
  764. iterator insert_equal(const_iterator hint, BOOST_RV_REF(value_type) mval)
  765. {
  766. BOOST_ASSERT(this->priv_in_range_or_end(hint));
  767. insert_commit_data data;
  768. this->priv_insert_equal_prepare(hint, mval, data);
  769. return this->priv_insert_commit(data, boost::move(mval));
  770. }
  771. template <class InIt>
  772. void insert_unique(InIt first, InIt last)
  773. {
  774. dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
  775. container_type &seq = this->m_data.m_seq;
  776. value_compare &val_cmp = this->priv_value_comp();
  777. //Step 1: put new elements in the back
  778. typename container_type::iterator const it = seq.insert(seq.cend(), first, last);
  779. //Step 2: sort them
  780. boost::movelib::pdqsort(it, seq.end(), val_cmp);
  781. //Step 3: only left unique values from the back not already present in the original range
  782. typename container_type::iterator const e = boost::movelib::inplace_set_unique_difference
  783. (it, seq.end(), seq.begin(), it, val_cmp);
  784. seq.erase(e, seq.cend());
  785. //it might be invalidated by erasing [e, seq.end) if e == it
  786. if (it != e)
  787. {
  788. //Step 4: merge both ranges
  789. (flat_tree_container_inplace_merge)(seq, it, this->priv_value_comp(), contiguous_tag);
  790. }
  791. }
  792. template <class InIt>
  793. void insert_equal(InIt first, InIt last)
  794. {
  795. if (first != last) {
  796. dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
  797. container_type &seq = this->m_data.m_seq;
  798. typename container_type::iterator const it = seq.insert(seq.cend(), first, last);
  799. (flat_tree_container_inplace_sort_ending)(seq, it, this->priv_value_comp(), contiguous_tag);
  800. (flat_tree_container_inplace_merge) (seq, it, this->priv_value_comp(), contiguous_tag);
  801. }
  802. }
  803. //Ordered
  804. template <class InIt>
  805. void insert_equal(ordered_range_t, InIt first, InIt last)
  806. {
  807. BOOST_ASSERT((is_sorted)(first, last, this->priv_value_comp()));
  808. const bool value = boost::container::dtl::
  809. has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
  810. (flat_tree_merge_equal)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
  811. }
  812. template <class InIt>
  813. void insert_unique(ordered_unique_range_t, InIt first, InIt last)
  814. {
  815. BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
  816. const bool value = boost::container::dtl::
  817. has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
  818. (flat_tree_merge_unique)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
  819. }
  820. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  821. template <class... Args>
  822. std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args)
  823. {
  824. typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
  825. get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
  826. stored_allocator_traits::construct(a, (value_type *)(&v), ::boost::forward<Args>(args)... );
  827. value_type *pval = move_detail::launder_cast<value_type *>(&v);
  828. value_destructor<stored_allocator_type, value_type> d(a, *pval);
  829. return this->insert_unique(::boost::move(*pval));
  830. }
  831. template <class... Args>
  832. iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args)
  833. {
  834. //hint checked in insert_unique
  835. typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
  836. get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
  837. stored_allocator_traits::construct(a, (value_type*)(&v), ::boost::forward<Args>(args)... );
  838. value_type *pval = move_detail::launder_cast<value_type *>(&v);
  839. value_destructor<stored_allocator_type, value_type> d(a, *pval);
  840. return this->insert_unique(hint, ::boost::move(*pval));
  841. }
  842. template <class... Args>
  843. iterator emplace_equal(BOOST_FWD_REF(Args)... args)
  844. {
  845. typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
  846. get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
  847. stored_allocator_traits::construct(a, (value_type*)(&v), ::boost::forward<Args>(args)... );
  848. value_type *pval = move_detail::launder_cast<value_type *>(&v);
  849. value_destructor<stored_allocator_type, value_type> d(a, *pval);
  850. return this->insert_equal(::boost::move(*pval));
  851. }
  852. template <class... Args>
  853. iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args)
  854. {
  855. //hint checked in insert_equal
  856. typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
  857. get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
  858. stored_allocator_traits::construct(a, (value_type*)(&v), ::boost::forward<Args>(args)... );
  859. value_type *pval = move_detail::launder_cast<value_type *>(&v);
  860. value_destructor<stored_allocator_type, value_type> d(a, *pval);
  861. return this->insert_equal(hint, ::boost::move(*pval));
  862. }
  863. template <class KeyType, class... Args>
  864. inline std::pair<iterator, bool> try_emplace
  865. (const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
  866. {
  867. std::pair<iterator,bool> ret;
  868. insert_commit_data data;
  869. const key_type & k = key;
  870. ret.second = hint == const_iterator()
  871. ? this->priv_insert_unique_prepare(k, data)
  872. : this->priv_insert_unique_prepare(hint, k, data);
  873. if(!ret.second){
  874. ret.first = this->nth(size_type(data.position - this->cbegin()));
  875. }
  876. else{
  877. ret.first = this->m_data.m_seq.emplace(data.position, try_emplace_t(), ::boost::forward<KeyType>(key), ::boost::forward<Args>(args)...);
  878. }
  879. return ret;
  880. }
  881. #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  882. #define BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE(N) \
  883. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  884. std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\
  885. {\
  886. typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
  887. get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
  888. stored_allocator_traits::construct(a, (value_type *)(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  889. value_type *pval = move_detail::launder_cast<value_type *>(&v);\
  890. value_destructor<stored_allocator_type, value_type> d(a, *pval);\
  891. return this->insert_unique(::boost::move(*pval));\
  892. }\
  893. \
  894. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  895. iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  896. {\
  897. typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
  898. get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
  899. stored_allocator_traits::construct(a, (value_type *)(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  900. value_type *pval = move_detail::launder_cast<value_type *>(&v);\
  901. value_destructor<stored_allocator_type, value_type> d(a, *pval);\
  902. return this->insert_unique(hint, ::boost::move(*pval));\
  903. }\
  904. \
  905. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  906. iterator emplace_equal(BOOST_MOVE_UREF##N)\
  907. {\
  908. typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
  909. get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
  910. stored_allocator_traits::construct(a, (value_type *)(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  911. value_type *pval = move_detail::launder_cast<value_type *>(&v);\
  912. value_destructor<stored_allocator_type, value_type> d(a, *pval);\
  913. return this->insert_equal(::boost::move(*pval));\
  914. }\
  915. \
  916. BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
  917. iterator emplace_hint_equal(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  918. {\
  919. typename dtl::aligned_storage <sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
  920. get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
  921. stored_allocator_traits::construct(a, (value_type *)(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  922. value_type *pval = move_detail::launder_cast<value_type *>(&v);\
  923. value_destructor<stored_allocator_type, value_type> d(a, *pval);\
  924. return this->insert_equal(hint, ::boost::move(*pval));\
  925. }\
  926. template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
  927. inline std::pair<iterator, bool>\
  928. try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  929. {\
  930. std::pair<iterator,bool> ret;\
  931. insert_commit_data data;\
  932. const key_type & k = key;\
  933. ret.second = hint == const_iterator()\
  934. ? this->priv_insert_unique_prepare(k, data)\
  935. : this->priv_insert_unique_prepare(hint, k, data);\
  936. \
  937. if(!ret.second){\
  938. ret.first = this->nth(size_type(data.position - this->cbegin()));\
  939. }\
  940. else{\
  941. ret.first = this->m_data.m_seq.emplace(data.position, try_emplace_t(), ::boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  942. }\
  943. return ret;\
  944. }\
  945. //
  946. BOOST_MOVE_ITERATE_0TO7(BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE)
  947. #undef BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE
  948. #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  949. template<class KeyType, class M>
  950. std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
  951. {
  952. const key_type& k = key;
  953. std::pair<iterator,bool> ret;
  954. insert_commit_data data;
  955. ret.second = hint == const_iterator()
  956. ? this->priv_insert_unique_prepare(k, data)
  957. : this->priv_insert_unique_prepare(hint, k, data);
  958. if(!ret.second){
  959. ret.first = this->nth(size_type(data.position - this->cbegin()));
  960. ret.first->second = boost::forward<M>(obj);
  961. }
  962. else{
  963. ret.first = this->m_data.m_seq.emplace(data.position, boost::forward<KeyType>(key), boost::forward<M>(obj));
  964. }
  965. return ret;
  966. }
  967. size_type erase(const key_type& k)
  968. {
  969. std::pair<iterator,iterator > itp = this->equal_range(k);
  970. size_type ret = static_cast<size_type>(itp.second-itp.first);
  971. if (ret){
  972. this->m_data.m_seq.erase(itp.first, itp.second);
  973. }
  974. return ret;
  975. }
  976. size_type erase_unique(const key_type& k)
  977. {
  978. const_iterator i = static_cast<const flat_tree &>(*this).find(k);
  979. size_type ret = static_cast<size_type>(i != this->cend());
  980. if (ret)
  981. this->erase(i);
  982. return ret;
  983. }
  984. template <class K>
  985. inline typename dtl::enable_if_c<
  986. dtl::is_transparent<key_compare>::value && //transparent
  987. !dtl::is_convertible<K, iterator>::value && //not convertible to iterator
  988. !dtl::is_convertible<K, const_iterator>::value //not convertible to const_iterator
  989. , size_type>::type
  990. erase(const K& k)
  991. {
  992. std::pair<iterator, iterator > itp = this->equal_range(k);
  993. size_type ret = static_cast<size_type>(itp.second - itp.first);
  994. if (ret) {
  995. this->m_data.m_seq.erase(itp.first, itp.second);
  996. }
  997. return ret;
  998. }
  999. template <class K>
  1000. inline typename dtl::enable_if_c<
  1001. dtl::is_transparent<key_compare>::value && //transparent
  1002. !dtl::is_convertible<K, iterator>::value && //not convertible to iterator
  1003. !dtl::is_convertible<K, const_iterator>::value //not convertible to const_iterator
  1004. , size_type>::type
  1005. erase_unique(const K& k)
  1006. {
  1007. const_iterator i = static_cast<const flat_tree&>(*this).find(k);
  1008. size_type ret = static_cast<size_type>(i != this->cend());
  1009. if (ret)
  1010. this->erase(i);
  1011. return ret;
  1012. }
  1013. inline iterator erase(const_iterator position)
  1014. { return this->m_data.m_seq.erase(position); }
  1015. inline iterator erase(const_iterator first, const_iterator last)
  1016. { return this->m_data.m_seq.erase(first, last); }
  1017. inline void clear()
  1018. { this->m_data.m_seq.clear(); }
  1019. //! <b>Effects</b>: Tries to deallocate the excess of memory created
  1020. // with previous allocations. The size of the vector is unchanged
  1021. //!
  1022. //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
  1023. //!
  1024. //! <b>Complexity</b>: Linear to size().
  1025. inline void shrink_to_fit()
  1026. { this->m_data.m_seq.shrink_to_fit(); }
  1027. inline iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
  1028. {
  1029. const bool value = boost::container::dtl::
  1030. has_member_function_callable_with_nth<container_type, size_type>::value;
  1031. return flat_tree_nth<iterator>(this->m_data.m_seq, n, dtl::bool_<value>());
  1032. }
  1033. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1034. const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
  1035. {
  1036. const bool value = boost::container::dtl::
  1037. has_member_function_callable_with_nth<container_type, size_type>::value;
  1038. return flat_tree_nth<const_iterator>(this->m_data.m_seq, n, dtl::bool_<value>());
  1039. }
  1040. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1041. size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
  1042. {
  1043. const bool value = boost::container::dtl::
  1044. has_member_function_callable_with_index_of<container_type, iterator>::value;
  1045. return flat_tree_index_of(this->m_data.m_seq, p, dtl::bool_<value>());
  1046. }
  1047. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1048. size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
  1049. {
  1050. const bool value = boost::container::dtl::
  1051. has_member_function_callable_with_index_of<container_type, const_iterator>::value;
  1052. return flat_tree_index_of(this->m_data.m_seq, p, dtl::bool_<value>());
  1053. }
  1054. // set operations:
  1055. BOOST_CONTAINER_ATTRIBUTE_NODISCARD
  1056. iterator find(const key_type& k)
  1057. {
  1058. iterator i = this->lower_bound(k);
  1059. iterator end_it = this->end();
  1060. if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
  1061. i = end_it;
  1062. }
  1063. return i;
  1064. }
  1065. BOOST_CONTAINER_ATTRIBUTE_NODISCARD
  1066. const_iterator find(const key_type& k) const
  1067. {
  1068. const_iterator i = this->lower_bound(k);
  1069. const_iterator end_it = this->cend();
  1070. if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
  1071. i = end_it;
  1072. }
  1073. return i;
  1074. }
  1075. template<class K>
  1076. BOOST_CONTAINER_ATTRIBUTE_NODISCARD
  1077. typename dtl::enable_if_transparent<key_compare, K, iterator>::type
  1078. find(const K& k)
  1079. {
  1080. iterator i = this->lower_bound(k);
  1081. iterator end_it = this->end();
  1082. if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
  1083. i = end_it;
  1084. }
  1085. return i;
  1086. }
  1087. template<class K>
  1088. BOOST_CONTAINER_ATTRIBUTE_NODISCARD
  1089. typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
  1090. find(const K& k) const
  1091. {
  1092. const_iterator i = this->lower_bound(k);
  1093. const_iterator end_it = this->cend();
  1094. if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
  1095. i = end_it;
  1096. }
  1097. return i;
  1098. }
  1099. BOOST_CONTAINER_ATTRIBUTE_NODISCARD
  1100. size_type count(const key_type& k) const
  1101. {
  1102. std::pair<const_iterator, const_iterator> p = this->equal_range(k);
  1103. size_type n = size_type(p.second - p.first);
  1104. return n;
  1105. }
  1106. template<class K>
  1107. BOOST_CONTAINER_ATTRIBUTE_NODISCARD
  1108. typename dtl::enable_if_transparent<key_compare, K, size_type>::type
  1109. count(const K& k) const
  1110. {
  1111. std::pair<const_iterator, const_iterator> p = this->equal_range(k);
  1112. size_type n = size_type(p.second - p.first);
  1113. return n;
  1114. }
  1115. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline bool contains(const key_type& x) const
  1116. { return this->find(x) != this->cend(); }
  1117. template<typename K>
  1118. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1119. typename dtl::enable_if_transparent<key_compare, K, bool>::type
  1120. contains(const K& x) const
  1121. { return this->find(x) != this->cend(); }
  1122. template<class C2>
  1123. inline void merge_unique(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
  1124. {
  1125. this->insert_unique( boost::make_move_iterator(source.begin())
  1126. , boost::make_move_iterator(source.end()));
  1127. }
  1128. template<class C2>
  1129. inline void merge_equal(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
  1130. {
  1131. this->insert_equal( boost::make_move_iterator(source.begin())
  1132. , boost::make_move_iterator(source.end()));
  1133. }
  1134. inline void merge_unique(flat_tree& source)
  1135. {
  1136. const bool value = boost::container::dtl::
  1137. has_member_function_callable_with_merge_unique<container_type, iterator, iterator, value_compare>::value;
  1138. (flat_tree_merge_unique)
  1139. ( this->m_data.m_seq
  1140. , boost::make_move_iterator(source.m_data.m_seq.begin())
  1141. , boost::make_move_iterator(source.m_data.m_seq.end())
  1142. , this->priv_value_comp()
  1143. , dtl::bool_<value>());
  1144. }
  1145. inline void merge_equal(flat_tree& source)
  1146. {
  1147. const bool value = boost::container::dtl::
  1148. has_member_function_callable_with_merge<container_type, iterator, iterator, value_compare>::value;
  1149. (flat_tree_merge_equal)
  1150. ( this->m_data.m_seq
  1151. , boost::make_move_iterator(source.m_data.m_seq.begin())
  1152. , boost::make_move_iterator(source.m_data.m_seq.end())
  1153. , this->priv_value_comp()
  1154. , dtl::bool_<value>());
  1155. }
  1156. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1157. iterator lower_bound(const key_type& k)
  1158. { return this->priv_lower_bound(this->begin(), this->end(), k); }
  1159. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1160. const_iterator lower_bound(const key_type& k) const
  1161. { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
  1162. template<class K>
  1163. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1164. typename dtl::enable_if_transparent<key_compare, K, iterator>::type
  1165. lower_bound(const K& k)
  1166. { return this->priv_lower_bound(this->begin(), this->end(), k); }
  1167. template<class K>
  1168. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1169. typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
  1170. lower_bound(const K& k) const
  1171. { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
  1172. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1173. iterator upper_bound(const key_type& k)
  1174. { return this->priv_upper_bound(this->begin(), this->end(), k); }
  1175. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1176. const_iterator upper_bound(const key_type& k) const
  1177. { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
  1178. template<class K>
  1179. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1180. typename dtl::enable_if_transparent<key_compare, K,iterator>::type
  1181. upper_bound(const K& k)
  1182. { return this->priv_upper_bound(this->begin(), this->end(), k); }
  1183. template<class K>
  1184. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1185. typename dtl::enable_if_transparent<key_compare, K,const_iterator>::type
  1186. upper_bound(const K& k) const
  1187. { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
  1188. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1189. std::pair<iterator,iterator> equal_range(const key_type& k)
  1190. { return this->priv_equal_range(this->begin(), this->end(), k); }
  1191. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1192. std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
  1193. { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
  1194. template<class K>
  1195. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1196. typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type
  1197. equal_range(const K& k)
  1198. { return this->priv_equal_range(this->begin(), this->end(), k); }
  1199. template<class K>
  1200. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1201. typename dtl::enable_if_transparent<key_compare, K,std::pair<const_iterator,const_iterator> >::type
  1202. equal_range(const K& k) const
  1203. { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
  1204. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1205. std::pair<iterator, iterator> lower_bound_range(const key_type& k)
  1206. { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
  1207. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1208. std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
  1209. { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
  1210. template<class K>
  1211. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1212. typename dtl::enable_if_transparent<key_compare, K,std::pair<iterator,iterator> >::type
  1213. lower_bound_range(const K& k)
  1214. { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
  1215. template<class K>
  1216. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1217. typename dtl::enable_if_transparent<key_compare, K,std::pair<const_iterator,const_iterator> >::type
  1218. lower_bound_range(const K& k) const
  1219. { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
  1220. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1221. size_type capacity() const
  1222. {
  1223. const bool value = boost::container::dtl::
  1224. has_member_function_callable_with_capacity<container_type>::value;
  1225. return (flat_tree_capacity)(this->m_data.m_seq, dtl::bool_<value>());
  1226. }
  1227. inline
  1228. void reserve(size_type cnt)
  1229. {
  1230. const bool value = boost::container::dtl::
  1231. has_member_function_callable_with_reserve<container_type, size_type>::value;
  1232. (flat_tree_reserve)(this->m_data.m_seq, cnt, dtl::bool_<value>());
  1233. }
  1234. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1235. container_type extract_sequence()
  1236. { return boost::move(m_data.m_seq); }
  1237. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1238. container_type &get_sequence_ref()
  1239. { return m_data.m_seq; }
  1240. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1241. const container_type &get_sequence_cref() const
  1242. { return m_data.m_seq; }
  1243. inline void adopt_sequence_equal(BOOST_RV_REF(container_type) seq)
  1244. {
  1245. (flat_tree_adopt_sequence_equal)( m_data.m_seq, boost::move(seq), this->priv_value_comp()
  1246. , dtl::bool_<is_contiguous_container<container_type>::value>());
  1247. }
  1248. inline void adopt_sequence_unique(BOOST_RV_REF(container_type) seq)
  1249. {
  1250. (flat_tree_adopt_sequence_unique)(m_data.m_seq, boost::move(seq), this->priv_value_comp()
  1251. , dtl::bool_<is_contiguous_container<container_type>::value>());
  1252. }
  1253. void adopt_sequence_equal(ordered_range_t, BOOST_RV_REF(container_type) seq)
  1254. {
  1255. BOOST_ASSERT((is_sorted)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
  1256. m_data.m_seq = boost::move(seq);
  1257. }
  1258. void adopt_sequence_unique(ordered_unique_range_t, BOOST_RV_REF(container_type) seq)
  1259. {
  1260. BOOST_ASSERT((is_sorted_and_unique)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
  1261. m_data.m_seq = boost::move(seq);
  1262. }
  1263. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1264. friend bool operator==(const flat_tree& x, const flat_tree& y)
  1265. {
  1266. return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());
  1267. }
  1268. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1269. friend bool operator<(const flat_tree& x, const flat_tree& y)
  1270. {
  1271. return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
  1272. }
  1273. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1274. friend bool operator!=(const flat_tree& x, const flat_tree& y)
  1275. { return !(x == y); }
  1276. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1277. friend bool operator>(const flat_tree& x, const flat_tree& y)
  1278. { return y < x; }
  1279. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1280. friend bool operator<=(const flat_tree& x, const flat_tree& y)
  1281. { return !(y < x); }
  1282. BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
  1283. friend bool operator>=(const flat_tree& x, const flat_tree& y)
  1284. { return !(x < y); }
  1285. inline friend void swap(flat_tree& x, flat_tree& y)
  1286. BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
  1287. { x.swap(y); }
  1288. private:
  1289. template <class InputIterator>
  1290. void priv_range_insertion_construct( bool unique_insertion, InputIterator first, InputIterator last)
  1291. {
  1292. //Use cend() as hint to achieve linear time for
  1293. //ordered ranges as required by the standard
  1294. //for the constructor
  1295. //Call end() every iteration as reallocation might have invalidated iterators
  1296. if(unique_insertion){
  1297. this->insert_unique(first, last);
  1298. }
  1299. else{
  1300. this->insert_equal (first, last);
  1301. }
  1302. }
  1303. inline bool priv_in_range_or_end(const_iterator pos) const
  1304. {
  1305. return (this->begin() <= pos) && (pos <= this->end());
  1306. }
  1307. // insert/erase
  1308. void priv_insert_equal_prepare
  1309. (const_iterator pos, const value_type& val, insert_commit_data &data)
  1310. {
  1311. // N1780
  1312. // To insert val at pos:
  1313. // if pos == end || val <= *pos
  1314. // if pos == begin || val >= *(pos-1)
  1315. // insert val before pos
  1316. // else
  1317. // insert val before upper_bound(val)
  1318. // else
  1319. // insert val before lower_bound(val)
  1320. const value_compare &val_cmp = this->m_data;
  1321. if(pos == this->cend() || !val_cmp(*pos, val)){
  1322. if (pos == this->cbegin() || !val_cmp(val, pos[-1])){
  1323. data.position = pos;
  1324. }
  1325. else{
  1326. data.position =
  1327. this->priv_upper_bound(this->cbegin(), pos, KeyOfValue()(val));
  1328. }
  1329. }
  1330. else{
  1331. data.position =
  1332. this->priv_lower_bound(pos, this->cend(), KeyOfValue()(val));
  1333. }
  1334. }
  1335. bool priv_insert_unique_prepare
  1336. (const_iterator b, const_iterator e, const key_type& k, insert_commit_data &commit_data)
  1337. {
  1338. const key_compare &key_cmp = this->priv_key_comp();
  1339. commit_data.position = this->priv_lower_bound(b, e, k);
  1340. return commit_data.position == e || key_cmp(k, KeyOfValue()(*commit_data.position));
  1341. }
  1342. inline bool priv_insert_unique_prepare
  1343. (const key_type& k, insert_commit_data &commit_data)
  1344. { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), k, commit_data); }
  1345. bool priv_insert_unique_prepare
  1346. (const_iterator pos, const key_type& k, insert_commit_data &commit_data)
  1347. {
  1348. //N1780. Props to Howard Hinnant!
  1349. //To insert k at pos:
  1350. //if pos == end || k <= *pos
  1351. // if pos == begin || k >= *(pos-1)
  1352. // insert k before pos
  1353. // else
  1354. // insert k before upper_bound(k)
  1355. //else if pos+1 == end || k <= *(pos+1)
  1356. // insert k after pos
  1357. //else
  1358. // insert k before lower_bound(k)
  1359. const key_compare &key_cmp = this->priv_key_comp();
  1360. const const_iterator cend_it = this->cend();
  1361. if(pos == cend_it || key_cmp(k, KeyOfValue()(*pos))){ //Check if k should go before end
  1362. const const_iterator cbeg = this->cbegin();
  1363. commit_data.position = pos;
  1364. if(pos == cbeg){ //If container is empty then insert it in the beginning
  1365. return true;
  1366. }
  1367. const_iterator prev(pos);
  1368. --prev;
  1369. if(key_cmp(KeyOfValue()(*prev), k)){ //If previous element was less, then it should go between prev and pos
  1370. return true;
  1371. }
  1372. else if(!key_cmp(k, KeyOfValue()(*prev))){ //If previous was equal then insertion should fail
  1373. commit_data.position = prev;
  1374. return false;
  1375. }
  1376. else{ //Previous was bigger so insertion hint was pointless, dispatch to hintless insertion
  1377. //but reduce the search between beg and prev as prev is bigger than k
  1378. return this->priv_insert_unique_prepare(cbeg, prev, k, commit_data);
  1379. }
  1380. }
  1381. else{
  1382. //The hint is before the insertion position, so insert it
  1383. //in the remaining range [pos, end)
  1384. return this->priv_insert_unique_prepare(pos, cend_it, k, commit_data);
  1385. }
  1386. }
  1387. template<class Convertible>
  1388. inline iterator priv_insert_commit
  1389. (insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible)
  1390. {
  1391. return this->m_data.m_seq.insert
  1392. ( commit_data.position
  1393. , boost::forward<Convertible>(convertible));
  1394. }
  1395. template <class RanIt, class K>
  1396. RanIt priv_lower_bound(RanIt first, const RanIt last,
  1397. const K & key) const
  1398. {
  1399. const Compare &key_cmp = this->m_data.get_comp();
  1400. KeyOfValue key_extract;
  1401. size_type len = static_cast<size_type>(last - first);
  1402. RanIt middle;
  1403. while (len) {
  1404. size_type step = len >> 1;
  1405. middle = first;
  1406. middle += difference_type(step);
  1407. if (key_cmp(key_extract(*middle), key)) {
  1408. first = ++middle;
  1409. len -= step + 1;
  1410. }
  1411. else{
  1412. len = step;
  1413. }
  1414. }
  1415. return first;
  1416. }
  1417. template <class RanIt, class K>
  1418. RanIt priv_upper_bound
  1419. (RanIt first, const RanIt last,const K & key) const
  1420. {
  1421. const Compare &key_cmp = this->m_data.get_comp();
  1422. KeyOfValue key_extract;
  1423. size_type len = static_cast<size_type>(last - first);
  1424. RanIt middle;
  1425. while (len) {
  1426. size_type step = len >> 1;
  1427. middle = first;
  1428. middle += difference_type(step);
  1429. if (key_cmp(key, key_extract(*middle))) {
  1430. len = step;
  1431. }
  1432. else{
  1433. first = ++middle;
  1434. len -= step + 1;
  1435. }
  1436. }
  1437. return first;
  1438. }
  1439. template <class RanIt, class K>
  1440. std::pair<RanIt, RanIt>
  1441. priv_equal_range(RanIt first, RanIt last, const K& key) const
  1442. {
  1443. const Compare &key_cmp = this->m_data.get_comp();
  1444. KeyOfValue key_extract;
  1445. size_type len = static_cast<size_type>(last - first);
  1446. RanIt middle;
  1447. while (len) {
  1448. size_type step = len >> 1;
  1449. middle = first;
  1450. middle += difference_type(step);
  1451. if (key_cmp(key_extract(*middle), key)){
  1452. first = ++middle;
  1453. len -= step + 1;
  1454. }
  1455. else if (key_cmp(key, key_extract(*middle))){
  1456. len = step;
  1457. }
  1458. else {
  1459. //Middle is equal to key
  1460. last = first;
  1461. last += difference_type(len);
  1462. RanIt const first_ret = this->priv_lower_bound(first, middle, key);
  1463. return std::pair<RanIt, RanIt>
  1464. ( first_ret, this->priv_upper_bound(++middle, last, key));
  1465. }
  1466. }
  1467. return std::pair<RanIt, RanIt>(first, first);
  1468. }
  1469. template<class RanIt, class K>
  1470. std::pair<RanIt, RanIt> priv_lower_bound_range(RanIt first, RanIt last, const K& k) const
  1471. {
  1472. const Compare &key_cmp = this->m_data.get_comp();
  1473. KeyOfValue key_extract;
  1474. RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb);
  1475. if(lb != last && !key_cmp(k, key_extract(*lb))){
  1476. ++ub;
  1477. }
  1478. return std::pair<RanIt, RanIt>(lb, ub);
  1479. }
  1480. };
  1481. } //namespace dtl {
  1482. } //namespace container {
  1483. //!has_trivial_destructor_after_move<> == true_type
  1484. //!specialization for optimizations
  1485. template <class T, class KeyOfValue,
  1486. class Compare, class AllocatorOrContainer>
  1487. struct has_trivial_destructor_after_move<boost::container::dtl::flat_tree<T, KeyOfValue, Compare, AllocatorOrContainer> >
  1488. {
  1489. typedef boost::container::dtl::flat_tree<T, KeyOfValue, Compare, AllocatorOrContainer> flat_tree;
  1490. typedef typename flat_tree::container_type container_type;
  1491. typedef typename flat_tree::key_compare key_compare;
  1492. BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move<container_type>::value &&
  1493. ::boost::has_trivial_destructor_after_move<key_compare>::value;
  1494. };
  1495. } //namespace boost {
  1496. #include <boost/container/detail/config_end.hpp>
  1497. #endif // BOOST_CONTAINER_FLAT_TREE_HPP