flat_tree.hpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2012. 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. #if defined(_MSC_VER)
  13. # pragma once
  14. #endif
  15. #include "config_begin.hpp"
  16. #include <boost/container/detail/workaround.hpp>
  17. #include <boost/container/container_fwd.hpp>
  18. #include <algorithm>
  19. #include <functional>
  20. #include <utility>
  21. #include <boost/type_traits/has_trivial_destructor.hpp>
  22. #include <boost/move/utility.hpp>
  23. #include <boost/container/detail/utilities.hpp>
  24. #include <boost/container/detail/pair.hpp>
  25. #include <boost/container/vector.hpp>
  26. #include <boost/container/detail/value_init.hpp>
  27. #include <boost/container/detail/destroyers.hpp>
  28. #include <boost/container/allocator_traits.hpp>
  29. #ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
  30. #include <boost/intrusive/pointer_traits.hpp>
  31. #endif
  32. #include <boost/aligned_storage.hpp>
  33. namespace boost {
  34. namespace container {
  35. namespace container_detail {
  36. template<class Compare, class Value, class KeyOfValue>
  37. class flat_tree_value_compare
  38. : private Compare
  39. {
  40. typedef Value first_argument_type;
  41. typedef Value second_argument_type;
  42. typedef bool return_type;
  43. public:
  44. flat_tree_value_compare()
  45. : Compare()
  46. {}
  47. flat_tree_value_compare(const Compare &pred)
  48. : Compare(pred)
  49. {}
  50. bool operator()(const Value& lhs, const Value& rhs) const
  51. {
  52. KeyOfValue key_extract;
  53. return Compare::operator()(key_extract(lhs), key_extract(rhs));
  54. }
  55. const Compare &get_comp() const
  56. { return *this; }
  57. Compare &get_comp()
  58. { return *this; }
  59. };
  60. template<class Pointer>
  61. struct get_flat_tree_iterators
  62. {
  63. #ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
  64. typedef Pointer iterator;
  65. typedef typename boost::intrusive::
  66. pointer_traits<Pointer>::element_type iterator_element_type;
  67. typedef typename boost::intrusive::
  68. pointer_traits<Pointer>:: template
  69. rebind_pointer<const iterator_element_type>::type const_iterator;
  70. #else //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
  71. typedef typename container_detail::
  72. vec_iterator<Pointer, false> iterator;
  73. typedef typename container_detail::
  74. vec_iterator<Pointer, true > const_iterator;
  75. #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
  76. typedef std::reverse_iterator<iterator> reverse_iterator;
  77. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  78. };
  79. template <class Key, class Value, class KeyOfValue,
  80. class Compare, class A>
  81. class flat_tree
  82. {
  83. typedef boost::container::vector<Value, A> vector_t;
  84. typedef A allocator_t;
  85. public:
  86. typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare;
  87. private:
  88. struct Data
  89. //Inherit from value_compare to do EBO
  90. : public value_compare
  91. {
  92. BOOST_COPYABLE_AND_MOVABLE(Data)
  93. public:
  94. Data()
  95. : value_compare(), m_vect()
  96. {}
  97. explicit Data(const Data &d)
  98. : value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect)
  99. {}
  100. Data(BOOST_RV_REF(Data) d)
  101. : value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect))
  102. {}
  103. Data(const Data &d, const A &a)
  104. : value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect, a)
  105. {}
  106. Data(BOOST_RV_REF(Data) d, const A &a)
  107. : value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect), a)
  108. {}
  109. explicit Data(const Compare &comp)
  110. : value_compare(comp), m_vect()
  111. {}
  112. Data(const Compare &comp, const allocator_t &alloc)
  113. : value_compare(comp), m_vect(alloc)
  114. {}
  115. explicit Data(const allocator_t &alloc)
  116. : value_compare(), m_vect(alloc)
  117. {}
  118. Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d)
  119. {
  120. this->value_compare::operator=(d);
  121. m_vect = d.m_vect;
  122. return *this;
  123. }
  124. Data& operator=(BOOST_RV_REF(Data) d)
  125. {
  126. this->value_compare::operator=(boost::move(static_cast<value_compare &>(d)));
  127. m_vect = boost::move(d.m_vect);
  128. return *this;
  129. }
  130. void swap(Data &d)
  131. {
  132. value_compare& mycomp = *this, & othercomp = d;
  133. boost::container::swap_dispatch(mycomp, othercomp);
  134. this->m_vect.swap(d.m_vect);
  135. }
  136. vector_t m_vect;
  137. };
  138. Data m_data;
  139. BOOST_COPYABLE_AND_MOVABLE(flat_tree)
  140. public:
  141. typedef typename vector_t::value_type value_type;
  142. typedef typename vector_t::pointer pointer;
  143. typedef typename vector_t::const_pointer const_pointer;
  144. typedef typename vector_t::reference reference;
  145. typedef typename vector_t::const_reference const_reference;
  146. typedef Key key_type;
  147. typedef Compare key_compare;
  148. typedef typename vector_t::allocator_type allocator_type;
  149. typedef typename vector_t::size_type size_type;
  150. typedef typename vector_t::difference_type difference_type;
  151. typedef typename vector_t::iterator iterator;
  152. typedef typename vector_t::const_iterator const_iterator;
  153. typedef typename vector_t::reverse_iterator reverse_iterator;
  154. typedef typename vector_t::const_reverse_iterator const_reverse_iterator;
  155. //!Standard extension
  156. typedef allocator_type stored_allocator_type;
  157. private:
  158. typedef allocator_traits<stored_allocator_type> stored_allocator_traits;
  159. public:
  160. flat_tree()
  161. : m_data()
  162. { }
  163. explicit flat_tree(const Compare& comp)
  164. : m_data(comp)
  165. { }
  166. flat_tree(const Compare& comp, const allocator_type& a)
  167. : m_data(comp, a)
  168. { }
  169. explicit flat_tree(const allocator_type& a)
  170. : m_data(a)
  171. { }
  172. flat_tree(const flat_tree& x)
  173. : m_data(x.m_data)
  174. { }
  175. flat_tree(BOOST_RV_REF(flat_tree) x)
  176. : m_data(boost::move(x.m_data))
  177. { }
  178. flat_tree(const flat_tree& x, const allocator_type &a)
  179. : m_data(x.m_data, a)
  180. { }
  181. flat_tree(BOOST_RV_REF(flat_tree) x, const allocator_type &a)
  182. : m_data(boost::move(x.m_data), a)
  183. { }
  184. template <class InputIterator>
  185. flat_tree( ordered_range_t, InputIterator first, InputIterator last
  186. , const Compare& comp = Compare()
  187. , const allocator_type& a = allocator_type())
  188. : m_data(comp, a)
  189. { this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last); }
  190. template <class InputIterator>
  191. flat_tree( bool unique_insertion
  192. , InputIterator first, InputIterator last
  193. , const Compare& comp = Compare()
  194. , const allocator_type& a = allocator_type())
  195. : m_data(comp, a)
  196. {
  197. //Use cend() as hint to achieve linear time for
  198. //ordered ranges as required by the standard
  199. //for the constructor
  200. //Call end() every iteration as reallocation might have invalidated iterators
  201. if(unique_insertion){
  202. for ( ; first != last; ++first){
  203. this->insert_unique(this->cend(), *first);
  204. }
  205. }
  206. else{
  207. for ( ; first != last; ++first){
  208. this->insert_equal(this->cend(), *first);
  209. }
  210. }
  211. }
  212. ~flat_tree()
  213. {}
  214. flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x)
  215. { m_data = x.m_data; return *this; }
  216. flat_tree& operator=(BOOST_RV_REF(flat_tree) mx)
  217. { m_data = boost::move(mx.m_data); return *this; }
  218. public:
  219. // accessors:
  220. Compare key_comp() const
  221. { return this->m_data.get_comp(); }
  222. allocator_type get_allocator() const
  223. { return this->m_data.m_vect.get_allocator(); }
  224. const stored_allocator_type &get_stored_allocator() const
  225. { return this->m_data.m_vect.get_stored_allocator(); }
  226. stored_allocator_type &get_stored_allocator()
  227. { return this->m_data.m_vect.get_stored_allocator(); }
  228. iterator begin()
  229. { return this->m_data.m_vect.begin(); }
  230. const_iterator begin() const
  231. { return this->cbegin(); }
  232. const_iterator cbegin() const
  233. { return this->m_data.m_vect.begin(); }
  234. iterator end()
  235. { return this->m_data.m_vect.end(); }
  236. const_iterator end() const
  237. { return this->cend(); }
  238. const_iterator cend() const
  239. { return this->m_data.m_vect.end(); }
  240. reverse_iterator rbegin()
  241. { return reverse_iterator(this->end()); }
  242. const_reverse_iterator rbegin() const
  243. { return this->crbegin(); }
  244. const_reverse_iterator crbegin() const
  245. { return const_reverse_iterator(this->cend()); }
  246. reverse_iterator rend()
  247. { return reverse_iterator(this->begin()); }
  248. const_reverse_iterator rend() const
  249. { return this->crend(); }
  250. const_reverse_iterator crend() const
  251. { return const_reverse_iterator(this->cbegin()); }
  252. bool empty() const
  253. { return this->m_data.m_vect.empty(); }
  254. size_type size() const
  255. { return this->m_data.m_vect.size(); }
  256. size_type max_size() const
  257. { return this->m_data.m_vect.max_size(); }
  258. void swap(flat_tree& other)
  259. { this->m_data.swap(other.m_data); }
  260. public:
  261. // insert/erase
  262. std::pair<iterator,bool> insert_unique(const value_type& val)
  263. {
  264. std::pair<iterator,bool> ret;
  265. insert_commit_data data;
  266. ret.second = this->priv_insert_unique_prepare(val, data);
  267. ret.first = ret.second ? this->priv_insert_commit(data, val)
  268. : iterator(vector_iterator_get_ptr(data.position));
  269. return ret;
  270. }
  271. std::pair<iterator,bool> insert_unique(BOOST_RV_REF(value_type) val)
  272. {
  273. std::pair<iterator,bool> ret;
  274. insert_commit_data data;
  275. ret.second = this->priv_insert_unique_prepare(val, data);
  276. ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val))
  277. : iterator(vector_iterator_get_ptr(data.position));
  278. return ret;
  279. }
  280. iterator insert_equal(const value_type& val)
  281. {
  282. iterator i = this->upper_bound(KeyOfValue()(val));
  283. i = this->m_data.m_vect.insert(i, val);
  284. return i;
  285. }
  286. iterator insert_equal(BOOST_RV_REF(value_type) mval)
  287. {
  288. iterator i = this->upper_bound(KeyOfValue()(mval));
  289. i = this->m_data.m_vect.insert(i, boost::move(mval));
  290. return i;
  291. }
  292. iterator insert_unique(const_iterator pos, const value_type& val)
  293. {
  294. std::pair<iterator,bool> ret;
  295. insert_commit_data data;
  296. return this->priv_insert_unique_prepare(pos, val, data)
  297. ? this->priv_insert_commit(data, val)
  298. : iterator(vector_iterator_get_ptr(data.position));
  299. }
  300. iterator insert_unique(const_iterator pos, BOOST_RV_REF(value_type) val)
  301. {
  302. std::pair<iterator,bool> ret;
  303. insert_commit_data data;
  304. return this->priv_insert_unique_prepare(pos, val, data)
  305. ? this->priv_insert_commit(data, boost::move(val))
  306. : iterator(vector_iterator_get_ptr(data.position));
  307. }
  308. iterator insert_equal(const_iterator pos, const value_type& val)
  309. {
  310. insert_commit_data data;
  311. this->priv_insert_equal_prepare(pos, val, data);
  312. return this->priv_insert_commit(data, val);
  313. }
  314. iterator insert_equal(const_iterator pos, BOOST_RV_REF(value_type) mval)
  315. {
  316. insert_commit_data data;
  317. this->priv_insert_equal_prepare(pos, mval, data);
  318. return this->priv_insert_commit(data, boost::move(mval));
  319. }
  320. template <class InIt>
  321. void insert_unique(InIt first, InIt last)
  322. {
  323. for ( ; first != last; ++first){
  324. this->insert_unique(*first);
  325. }
  326. }
  327. template <class InIt>
  328. void insert_equal(InIt first, InIt last
  329. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  330. , typename container_detail::enable_if_c
  331. < container_detail::is_input_iterator<InIt>::value
  332. >::type * = 0
  333. #endif
  334. )
  335. { this->priv_insert_equal_loop(first, last); }
  336. template <class InIt>
  337. void insert_equal(InIt first, InIt last
  338. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  339. , typename container_detail::enable_if_c
  340. < !container_detail::is_input_iterator<InIt>::value
  341. >::type * = 0
  342. #endif
  343. )
  344. {
  345. const size_type len = static_cast<size_type>(std::distance(first, last));
  346. this->reserve(this->size()+len);
  347. this->priv_insert_equal_loop(first, last);
  348. }
  349. //Ordered
  350. template <class InIt>
  351. void insert_equal(ordered_range_t, InIt first, InIt last
  352. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  353. , typename container_detail::enable_if_c
  354. < container_detail::is_input_iterator<InIt>::value
  355. >::type * = 0
  356. #endif
  357. )
  358. { this->priv_insert_equal_loop_ordered(first, last); }
  359. template <class FwdIt>
  360. void insert_equal(ordered_range_t, FwdIt first, FwdIt last
  361. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  362. , typename container_detail::enable_if_c
  363. < !container_detail::is_input_iterator<FwdIt>::value &&
  364. container_detail::is_forward_iterator<FwdIt>::value
  365. >::type * = 0
  366. #endif
  367. )
  368. {
  369. const size_type len = static_cast<size_type>(std::distance(first, last));
  370. this->reserve(this->size()+len);
  371. this->priv_insert_equal_loop_ordered(first, last);
  372. }
  373. template <class BidirIt>
  374. void insert_equal(ordered_range_t, BidirIt first, BidirIt last
  375. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  376. , typename container_detail::enable_if_c
  377. < !container_detail::is_input_iterator<BidirIt>::value &&
  378. !container_detail::is_forward_iterator<BidirIt>::value
  379. >::type * = 0
  380. #endif
  381. )
  382. {
  383. size_type len = static_cast<size_type>(std::distance(first, last));
  384. const size_type BurstSize = 16;
  385. size_type positions[BurstSize];
  386. //Prereserve all memory so that iterators are not invalidated
  387. this->reserve(this->size()+len);
  388. const const_iterator b(this->cbegin());
  389. const_iterator pos(b);
  390. //Loop in burst sizes
  391. while(len){
  392. const size_type burst = len < BurstSize ? len : BurstSize;
  393. const const_iterator ce(this->cend());
  394. len -= burst;
  395. for(size_type i = 0; i != burst; ++i){
  396. //Get the insertion position for each key
  397. pos = const_cast<const flat_tree&>(*this).priv_upper_bound(pos, ce, KeyOfValue()(*first));
  398. positions[i] = static_cast<size_type>(pos - b);
  399. ++first;
  400. }
  401. //Insert all in a single step in the precalculated positions
  402. this->m_data.m_vect.insert_ordered_at(burst, positions + burst, first);
  403. //Next search position updated
  404. pos += burst;
  405. }
  406. }
  407. template <class InIt>
  408. void insert_unique(ordered_unique_range_t, InIt first, InIt last
  409. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  410. , typename container_detail::enable_if_c
  411. < container_detail::is_input_iterator<InIt>::value ||
  412. container_detail::is_forward_iterator<InIt>::value
  413. >::type * = 0
  414. #endif
  415. )
  416. {
  417. const_iterator pos(this->cend());
  418. for ( ; first != last; ++first){
  419. pos = this->insert_unique(pos, *first);
  420. ++pos;
  421. }
  422. }
  423. template <class BidirIt>
  424. void insert_unique(ordered_unique_range_t, BidirIt first, BidirIt last
  425. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  426. , typename container_detail::enable_if_c
  427. < !(container_detail::is_input_iterator<BidirIt>::value ||
  428. container_detail::is_forward_iterator<BidirIt>::value)
  429. >::type * = 0
  430. #endif
  431. )
  432. {
  433. size_type len = static_cast<size_type>(std::distance(first, last));
  434. const size_type BurstSize = 16;
  435. size_type positions[BurstSize];
  436. size_type skips[BurstSize];
  437. //Prereserve all memory so that iterators are not invalidated
  438. this->reserve(this->size()+len);
  439. const const_iterator b(this->cbegin());
  440. const_iterator pos(b);
  441. const value_compare &value_comp = this->m_data;
  442. skips[0u] = 0u;
  443. //Loop in burst sizes
  444. while(len){
  445. const size_type burst = len < BurstSize ? len : BurstSize;
  446. size_type unique_burst = 0u;
  447. const const_iterator ce(this->cend());
  448. while(unique_burst < burst && len > 0){
  449. //Get the insertion position for each key
  450. const value_type & val = *first++;
  451. --len;
  452. pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, ce, KeyOfValue()(val));
  453. //Check if already present
  454. if(pos != ce && !value_comp(val, *pos)){
  455. if(unique_burst > 0){
  456. ++skips[unique_burst-1];
  457. }
  458. continue;
  459. }
  460. //If not present, calculate position
  461. positions[unique_burst] = static_cast<size_type>(pos - b);
  462. skips[unique_burst++] = 0u;
  463. }
  464. if(unique_burst){
  465. //Insert all in a single step in the precalculated positions
  466. this->m_data.m_vect.insert_ordered_at(unique_burst, positions + unique_burst, skips + unique_burst, first);
  467. //Next search position updated
  468. pos += unique_burst;
  469. }
  470. }
  471. }
  472. #ifdef BOOST_CONTAINER_PERFECT_FORWARDING
  473. template <class... Args>
  474. std::pair<iterator, bool> emplace_unique(Args&&... args)
  475. {
  476. aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
  477. value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
  478. stored_allocator_type &a = this->get_stored_allocator();
  479. stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
  480. value_destructor<stored_allocator_type> d(a, val);
  481. return this->insert_unique(::boost::move(val));
  482. }
  483. template <class... Args>
  484. iterator emplace_hint_unique(const_iterator hint, Args&&... args)
  485. {
  486. aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
  487. value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
  488. stored_allocator_type &a = this->get_stored_allocator();
  489. stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
  490. value_destructor<stored_allocator_type> d(a, val);
  491. return this->insert_unique(hint, ::boost::move(val));
  492. }
  493. template <class... Args>
  494. iterator emplace_equal(Args&&... args)
  495. {
  496. aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
  497. value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
  498. stored_allocator_type &a = this->get_stored_allocator();
  499. stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
  500. value_destructor<stored_allocator_type> d(a, val);
  501. return this->insert_equal(::boost::move(val));
  502. }
  503. template <class... Args>
  504. iterator emplace_hint_equal(const_iterator hint, Args&&... args)
  505. {
  506. aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
  507. value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));
  508. stored_allocator_type &a = this->get_stored_allocator();
  509. stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
  510. value_destructor<stored_allocator_type> d(a, val);
  511. return this->insert_equal(hint, ::boost::move(val));
  512. }
  513. #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
  514. #define BOOST_PP_LOCAL_MACRO(n) \
  515. BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
  516. std::pair<iterator, bool> \
  517. emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  518. { \
  519. aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
  520. value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); \
  521. stored_allocator_type &a = this->get_stored_allocator(); \
  522. stored_allocator_traits::construct(a, &val \
  523. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
  524. value_destructor<stored_allocator_type> d(a, val); \
  525. return this->insert_unique(::boost::move(val)); \
  526. } \
  527. \
  528. BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
  529. iterator emplace_hint_unique(const_iterator hint \
  530. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  531. { \
  532. aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
  533. value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); \
  534. stored_allocator_type &a = this->get_stored_allocator(); \
  535. stored_allocator_traits::construct(a, &val \
  536. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
  537. value_destructor<stored_allocator_type> d(a, val); \
  538. return this->insert_unique(hint, ::boost::move(val)); \
  539. } \
  540. \
  541. BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
  542. iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  543. { \
  544. aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
  545. value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); \
  546. stored_allocator_type &a = this->get_stored_allocator(); \
  547. stored_allocator_traits::construct(a, &val \
  548. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
  549. value_destructor<stored_allocator_type> d(a, val); \
  550. return this->insert_equal(::boost::move(val)); \
  551. } \
  552. \
  553. BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
  554. iterator emplace_hint_equal(const_iterator hint \
  555. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  556. { \
  557. aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
  558. value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); \
  559. stored_allocator_type &a = this->get_stored_allocator(); \
  560. stored_allocator_traits::construct(a, &val \
  561. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
  562. value_destructor<stored_allocator_type> d(a, val); \
  563. return this->insert_equal(hint, ::boost::move(val)); \
  564. } \
  565. //!
  566. #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
  567. #include BOOST_PP_LOCAL_ITERATE()
  568. #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
  569. iterator erase(const_iterator position)
  570. { return this->m_data.m_vect.erase(position); }
  571. size_type erase(const key_type& k)
  572. {
  573. std::pair<iterator,iterator > itp = this->equal_range(k);
  574. size_type ret = static_cast<size_type>(itp.second-itp.first);
  575. if (ret){
  576. this->m_data.m_vect.erase(itp.first, itp.second);
  577. }
  578. return ret;
  579. }
  580. iterator erase(const_iterator first, const_iterator last)
  581. { return this->m_data.m_vect.erase(first, last); }
  582. void clear()
  583. { this->m_data.m_vect.clear(); }
  584. //! <b>Effects</b>: Tries to deallocate the excess of memory created
  585. // with previous allocations. The size of the vector is unchanged
  586. //!
  587. //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
  588. //!
  589. //! <b>Complexity</b>: Linear to size().
  590. void shrink_to_fit()
  591. { this->m_data.m_vect.shrink_to_fit(); }
  592. // set operations:
  593. iterator find(const key_type& k)
  594. {
  595. iterator i = this->lower_bound(k);
  596. iterator end_it = this->end();
  597. if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
  598. i = end_it;
  599. }
  600. return i;
  601. }
  602. const_iterator find(const key_type& k) const
  603. {
  604. const_iterator i = this->lower_bound(k);
  605. const_iterator end_it = this->cend();
  606. if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
  607. i = end_it;
  608. }
  609. return i;
  610. }
  611. size_type count(const key_type& k) const
  612. {
  613. std::pair<const_iterator, const_iterator> p = this->equal_range(k);
  614. size_type n = p.second - p.first;
  615. return n;
  616. }
  617. iterator lower_bound(const key_type& k)
  618. { return this->priv_lower_bound(this->begin(), this->end(), k); }
  619. const_iterator lower_bound(const key_type& k) const
  620. { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
  621. iterator upper_bound(const key_type& k)
  622. { return this->priv_upper_bound(this->begin(), this->end(), k); }
  623. const_iterator upper_bound(const key_type& k) const
  624. { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
  625. std::pair<iterator,iterator> equal_range(const key_type& k)
  626. { return this->priv_equal_range(this->begin(), this->end(), k); }
  627. std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
  628. { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
  629. size_type capacity() const
  630. { return this->m_data.m_vect.capacity(); }
  631. void reserve(size_type cnt)
  632. { this->m_data.m_vect.reserve(cnt); }
  633. private:
  634. struct insert_commit_data
  635. {
  636. const_iterator position;
  637. };
  638. // insert/erase
  639. void priv_insert_equal_prepare
  640. (const_iterator pos, const value_type& val, insert_commit_data &data)
  641. {
  642. // N1780
  643. // To insert val at pos:
  644. // if pos == end || val <= *pos
  645. // if pos == begin || val >= *(pos-1)
  646. // insert val before pos
  647. // else
  648. // insert val before upper_bound(val)
  649. // else
  650. // insert val before lower_bound(val)
  651. const value_compare &value_comp = this->m_data;
  652. if(pos == this->cend() || !value_comp(*pos, val)){
  653. if (pos == this->cbegin() || !value_comp(val, pos[-1])){
  654. data.position = pos;
  655. }
  656. else{
  657. data.position =
  658. this->priv_upper_bound(this->cbegin(), pos, KeyOfValue()(val));
  659. }
  660. }
  661. else{
  662. data.position =
  663. this->priv_lower_bound(pos, this->cend(), KeyOfValue()(val));
  664. }
  665. }
  666. bool priv_insert_unique_prepare
  667. (const_iterator b, const_iterator e, const value_type& val, insert_commit_data &commit_data)
  668. {
  669. const value_compare &value_comp = this->m_data;
  670. commit_data.position = this->priv_lower_bound(b, e, KeyOfValue()(val));
  671. return commit_data.position == e || value_comp(val, *commit_data.position);
  672. }
  673. bool priv_insert_unique_prepare
  674. (const value_type& val, insert_commit_data &commit_data)
  675. { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), val, commit_data); }
  676. bool priv_insert_unique_prepare
  677. (const_iterator pos, const value_type& val, insert_commit_data &commit_data)
  678. {
  679. //N1780. Props to Howard Hinnant!
  680. //To insert val at pos:
  681. //if pos == end || val <= *pos
  682. // if pos == begin || val >= *(pos-1)
  683. // insert val before pos
  684. // else
  685. // insert val before upper_bound(val)
  686. //else if pos+1 == end || val <= *(pos+1)
  687. // insert val after pos
  688. //else
  689. // insert val before lower_bound(val)
  690. const value_compare &value_comp = this->m_data;
  691. const const_iterator cend_it = this->cend();
  692. if(pos == cend_it || value_comp(val, *pos)){ //Check if val should go before end
  693. const const_iterator cbeg = this->cbegin();
  694. commit_data.position = pos;
  695. if(pos == cbeg){ //If container is empty then insert it in the beginning
  696. return true;
  697. }
  698. const_iterator prev(pos);
  699. --prev;
  700. if(value_comp(*prev, val)){ //If previous element was less, then it should go between prev and pos
  701. return true;
  702. }
  703. else if(!value_comp(val, *prev)){ //If previous was equal then insertion should fail
  704. commit_data.position = prev;
  705. return false;
  706. }
  707. else{ //Previous was bigger so insertion hint was pointless, dispatch to hintless insertion
  708. //but reduce the search between beg and prev as prev is bigger than val
  709. return this->priv_insert_unique_prepare(cbeg, prev, val, commit_data);
  710. }
  711. }
  712. else{
  713. //The hint is before the insertion position, so insert it
  714. //in the remaining range [pos, end)
  715. return this->priv_insert_unique_prepare(pos, cend_it, val, commit_data);
  716. }
  717. }
  718. template<class Convertible>
  719. iterator priv_insert_commit
  720. (insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible)
  721. {
  722. return this->m_data.m_vect.insert
  723. ( commit_data.position
  724. , boost::forward<Convertible>(convertible));
  725. }
  726. template <class RanIt>
  727. RanIt priv_lower_bound(RanIt first, RanIt last,
  728. const key_type & key) const
  729. {
  730. const Compare &key_cmp = this->m_data.get_comp();
  731. KeyOfValue key_extract;
  732. size_type len = static_cast<size_type>(last - first);
  733. RanIt middle;
  734. while (len) {
  735. size_type half = len >> 1;
  736. middle = first;
  737. middle += half;
  738. if (key_cmp(key_extract(*middle), key)) {
  739. ++middle;
  740. first = middle;
  741. len = len - half - 1;
  742. }
  743. else
  744. len = half;
  745. }
  746. return first;
  747. }
  748. template <class RanIt>
  749. RanIt priv_upper_bound(RanIt first, RanIt last,
  750. const key_type & key) const
  751. {
  752. const Compare &key_cmp = this->m_data.get_comp();
  753. KeyOfValue key_extract;
  754. size_type len = static_cast<size_type>(last - first);
  755. RanIt middle;
  756. while (len) {
  757. size_type half = len >> 1;
  758. middle = first;
  759. middle += half;
  760. if (key_cmp(key, key_extract(*middle))) {
  761. len = half;
  762. }
  763. else{
  764. first = ++middle;
  765. len = len - half - 1;
  766. }
  767. }
  768. return first;
  769. }
  770. template <class RanIt>
  771. std::pair<RanIt, RanIt>
  772. priv_equal_range(RanIt first, RanIt last, const key_type& key) const
  773. {
  774. const Compare &key_cmp = this->m_data.get_comp();
  775. KeyOfValue key_extract;
  776. size_type len = static_cast<size_type>(last - first);
  777. RanIt middle;
  778. while (len) {
  779. size_type half = len >> 1;
  780. middle = first;
  781. middle += half;
  782. if (key_cmp(key_extract(*middle), key)){
  783. first = middle;
  784. ++first;
  785. len = len - half - 1;
  786. }
  787. else if (key_cmp(key, key_extract(*middle))){
  788. len = half;
  789. }
  790. else {
  791. //Middle is equal to key
  792. last = first;
  793. last += len;
  794. first = this->priv_lower_bound(first, middle, key);
  795. return std::pair<RanIt, RanIt> (first, this->priv_upper_bound(++middle, last, key));
  796. }
  797. }
  798. return std::pair<RanIt, RanIt>(first, first);
  799. }
  800. template<class InIt>
  801. void priv_insert_equal_loop(InIt first, InIt last)
  802. {
  803. for ( ; first != last; ++first){
  804. this->insert_equal(*first);
  805. }
  806. }
  807. template<class InIt>
  808. void priv_insert_equal_loop_ordered(InIt first, InIt last)
  809. {
  810. const_iterator pos(this->cend());
  811. for ( ; first != last; ++first){
  812. //If ordered, then try hint version
  813. //to achieve constant-time complexity per insertion
  814. pos = this->insert_equal(pos, *first);
  815. ++pos;
  816. }
  817. }
  818. };
  819. template <class Key, class Value, class KeyOfValue,
  820. class Compare, class A>
  821. inline bool
  822. operator==(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
  823. const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
  824. {
  825. return x.size() == y.size() &&
  826. std::equal(x.begin(), x.end(), y.begin());
  827. }
  828. template <class Key, class Value, class KeyOfValue,
  829. class Compare, class A>
  830. inline bool
  831. operator<(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
  832. const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
  833. {
  834. return std::lexicographical_compare(x.begin(), x.end(),
  835. y.begin(), y.end());
  836. }
  837. template <class Key, class Value, class KeyOfValue,
  838. class Compare, class A>
  839. inline bool
  840. operator!=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
  841. const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
  842. { return !(x == y); }
  843. template <class Key, class Value, class KeyOfValue,
  844. class Compare, class A>
  845. inline bool
  846. operator>(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
  847. const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
  848. { return y < x; }
  849. template <class Key, class Value, class KeyOfValue,
  850. class Compare, class A>
  851. inline bool
  852. operator<=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
  853. const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
  854. { return !(y < x); }
  855. template <class Key, class Value, class KeyOfValue,
  856. class Compare, class A>
  857. inline bool
  858. operator>=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
  859. const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
  860. { return !(x < y); }
  861. template <class Key, class Value, class KeyOfValue,
  862. class Compare, class A>
  863. inline void
  864. swap(flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
  865. flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
  866. { x.swap(y); }
  867. } //namespace container_detail {
  868. } //namespace container {
  869. /*
  870. //!has_trivial_destructor_after_move<> == true_type
  871. //!specialization for optimizations
  872. template <class K, class V, class KOV,
  873. class C, class A>
  874. struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<K, V, KOV, C, A> >
  875. {
  876. static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value;
  877. };
  878. */
  879. } //namespace boost {
  880. #include <boost/container/detail/config_end.hpp>
  881. #endif // BOOST_CONTAINER_FLAT_TREE_HPP