/Src/Dependencies/Boost/boost/interprocess/containers/container/detail/flat_tree.hpp

http://hadesmem.googlecode.com/ · C++ Header · 875 lines · 642 code · 128 blank · 105 comment · 50 complexity · f6900d2f5796d69122f1bc74c5f118a9 MD5 · raw file

  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2009. 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. // The Loki Library
  11. // Copyright (c) 2001 by Andrei Alexandrescu
  12. // This code accompanies the book:
  13. // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
  14. // Patterns Applied". Copyright (c) 2001. Addison-Wesley.
  15. // Permission to use, copy, modify, distribute and sell this software for any
  16. // purpose is hereby granted without fee, provided that the above copyright
  17. // notice appear in all copies and that both that copyright notice and this
  18. // permission notice appear in supporting documentation.
  19. // The author or Addison-Welsey Longman make no representations about the
  20. // suitability of this software for any purpose. It is provided "as is"
  21. // without express or implied warranty.
  22. ///////////////////////////////////////////////////////////////////////////////
  23. //
  24. // Parts of this file come from AssocVector.h file from Loki library
  25. //
  26. ////////////////////////////////////////////////////////////////////////////////
  27. #ifndef BOOST_CONTAINERS_FLAT_TREE_HPP
  28. #define BOOST_CONTAINERS_FLAT_TREE_HPP
  29. #if (defined _MSC_VER) && (_MSC_VER >= 1200)
  30. # pragma once
  31. #endif
  32. #include "config_begin.hpp"
  33. #include INCLUDE_BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
  34. #include INCLUDE_BOOST_CONTAINER_CONTAINER_FWD_HPP
  35. #include <algorithm>
  36. #include <functional>
  37. #include <utility>
  38. #include <boost/type_traits/has_trivial_destructor.hpp>
  39. #include INCLUDE_BOOST_CONTAINER_MOVE_HPP
  40. #include INCLUDE_BOOST_CONTAINER_DETAIL_UTILITIES_HPP
  41. #include INCLUDE_BOOST_CONTAINER_DETAIL_PAIR_HPP
  42. #include INCLUDE_BOOST_CONTAINER_VECTOR_HPP
  43. #include INCLUDE_BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
  44. #include INCLUDE_BOOST_CONTAINER_DETAIL_DESTROYERS_HPP
  45. namespace boost {
  46. namespace container {
  47. namespace containers_detail {
  48. template<class Compare, class Value, class KeyOfValue>
  49. class flat_tree_value_compare
  50. : private Compare
  51. {
  52. typedef Value first_argument_type;
  53. typedef Value second_argument_type;
  54. typedef bool return_type;
  55. public:
  56. flat_tree_value_compare(const Compare &pred)
  57. : Compare(pred)
  58. {}
  59. bool operator()(const Value& lhs, const Value& rhs) const
  60. {
  61. KeyOfValue key_extract;
  62. return Compare::operator()(key_extract(lhs), key_extract(rhs));
  63. }
  64. const Compare &get_comp() const
  65. { return *this; }
  66. Compare &get_comp()
  67. { return *this; }
  68. };
  69. template<class Pointer>
  70. struct get_flat_tree_iterators
  71. {
  72. typedef typename containers_detail::
  73. vector_iterator<Pointer> iterator;
  74. typedef typename containers_detail::
  75. vector_const_iterator<Pointer> const_iterator;
  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 Alloc>
  81. class flat_tree
  82. {
  83. typedef boost::container::vector<Value, Alloc> vector_t;
  84. typedef Alloc 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. private:
  93. BOOST_MOVE_MACRO_COPYABLE_AND_MOVABLE(Data)
  94. public:
  95. Data(const Data &d)
  96. : value_compare(d), m_vect(d.m_vect)
  97. {}
  98. Data(const Compare &comp,
  99. const vector_t &vect)
  100. : value_compare(comp), m_vect(vect){}
  101. Data(const value_compare &comp,
  102. const vector_t &vect)
  103. : value_compare(comp), m_vect(vect){}
  104. Data(const Compare &comp,
  105. const allocator_t &alloc)
  106. : value_compare(comp), m_vect(alloc){}
  107. Data& operator=(BOOST_MOVE_MACRO_COPY_ASSIGN_REF(Data) d)
  108. {
  109. this->value_compare::operator=(d);
  110. m_vect = d.m_vect;
  111. return *this;
  112. }
  113. Data& operator=(BOOST_MOVE_MACRO_RV_REF(Data) d)
  114. {
  115. this->value_compare::operator=(BOOST_CONTAINER_MOVE_NAMESPACE::move(static_cast<value_compare &>(d)));
  116. m_vect = BOOST_CONTAINER_MOVE_NAMESPACE::move(d.m_vect);
  117. return *this;
  118. }
  119. vector_t m_vect;
  120. };
  121. Data m_data;
  122. BOOST_MOVE_MACRO_COPYABLE_AND_MOVABLE(flat_tree)
  123. public:
  124. typedef typename vector_t::value_type value_type;
  125. typedef typename vector_t::pointer pointer;
  126. typedef typename vector_t::const_pointer const_pointer;
  127. typedef typename vector_t::reference reference;
  128. typedef typename vector_t::const_reference const_reference;
  129. typedef Key key_type;
  130. typedef Compare key_compare;
  131. typedef typename vector_t::allocator_type allocator_type;
  132. typedef allocator_type stored_allocator_type;
  133. typedef typename allocator_type::size_type size_type;
  134. typedef typename allocator_type::difference_type difference_type;
  135. typedef typename vector_t::iterator iterator;
  136. typedef typename vector_t::const_iterator const_iterator;
  137. typedef std::reverse_iterator<iterator> reverse_iterator;
  138. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  139. // allocation/deallocation
  140. flat_tree(const Compare& comp = Compare(),
  141. const allocator_type& a = allocator_type())
  142. : m_data(comp, a)
  143. { }
  144. flat_tree(const flat_tree& x)
  145. : m_data(x.m_data, x.m_data.m_vect)
  146. { }
  147. flat_tree(BOOST_MOVE_MACRO_RV_REF(flat_tree) x)
  148. : m_data(BOOST_CONTAINER_MOVE_NAMESPACE::move(x.m_data))
  149. { }
  150. template <class InputIterator>
  151. flat_tree( ordered_range_t, InputIterator first, InputIterator last
  152. , const Compare& comp = Compare()
  153. , const allocator_type& a = allocator_type())
  154. : m_data(comp, a)
  155. { this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last); }
  156. ~flat_tree()
  157. { }
  158. flat_tree& operator=(BOOST_MOVE_MACRO_COPY_ASSIGN_REF(flat_tree) x)
  159. { m_data = x.m_data; return *this; }
  160. flat_tree& operator=(BOOST_MOVE_MACRO_RV_REF(flat_tree) mx)
  161. { m_data = BOOST_CONTAINER_MOVE_NAMESPACE::move(mx.m_data); return *this; }
  162. public:
  163. // accessors:
  164. Compare key_comp() const
  165. { return this->m_data.get_comp(); }
  166. allocator_type get_allocator() const
  167. { return this->m_data.m_vect.get_allocator(); }
  168. const stored_allocator_type &get_stored_allocator() const
  169. { return this->m_data.m_vect.get_stored_allocator(); }
  170. stored_allocator_type &get_stored_allocator()
  171. { return this->m_data.m_vect.get_stored_allocator(); }
  172. iterator begin()
  173. { return this->m_data.m_vect.begin(); }
  174. const_iterator begin() const
  175. { return this->cbegin(); }
  176. const_iterator cbegin() const
  177. { return this->m_data.m_vect.begin(); }
  178. iterator end()
  179. { return this->m_data.m_vect.end(); }
  180. const_iterator end() const
  181. { return this->cend(); }
  182. const_iterator cend() const
  183. { return this->m_data.m_vect.end(); }
  184. reverse_iterator rbegin()
  185. { return reverse_iterator(this->end()); }
  186. const_reverse_iterator rbegin() const
  187. { return this->crbegin(); }
  188. const_reverse_iterator crbegin() const
  189. { return const_reverse_iterator(this->cend()); }
  190. reverse_iterator rend()
  191. { return reverse_iterator(this->begin()); }
  192. const_reverse_iterator rend() const
  193. { return this->crend(); }
  194. const_reverse_iterator crend() const
  195. { return const_reverse_iterator(this->cbegin()); }
  196. bool empty() const
  197. { return this->m_data.m_vect.empty(); }
  198. size_type size() const
  199. { return this->m_data.m_vect.size(); }
  200. size_type max_size() const
  201. { return this->m_data.m_vect.max_size(); }
  202. void swap(flat_tree& other)
  203. {
  204. value_compare& mycomp = this->m_data;
  205. value_compare& othercomp = other.m_data;
  206. containers_detail::do_swap(mycomp, othercomp);
  207. vector_t & myvect = this->m_data.m_vect;
  208. vector_t & othervect = other.m_data.m_vect;
  209. myvect.swap(othervect);
  210. }
  211. public:
  212. // insert/erase
  213. std::pair<iterator,bool> insert_unique(const value_type& val)
  214. {
  215. insert_commit_data data;
  216. std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
  217. if(ret.second){
  218. ret.first = priv_insert_commit(data, val);
  219. }
  220. return ret;
  221. }
  222. std::pair<iterator,bool> insert_unique(BOOST_MOVE_MACRO_RV_REF(value_type) val)
  223. {
  224. insert_commit_data data;
  225. std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
  226. if(ret.second){
  227. ret.first = priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(val));
  228. }
  229. return ret;
  230. }
  231. iterator insert_equal(const value_type& val)
  232. {
  233. iterator i = this->upper_bound(KeyOfValue()(val));
  234. i = this->m_data.m_vect.insert(i, val);
  235. return i;
  236. }
  237. iterator insert_equal(BOOST_MOVE_MACRO_RV_REF(value_type) mval)
  238. {
  239. iterator i = this->upper_bound(KeyOfValue()(mval));
  240. i = this->m_data.m_vect.insert(i, BOOST_CONTAINER_MOVE_NAMESPACE::move(mval));
  241. return i;
  242. }
  243. iterator insert_unique(const_iterator pos, const value_type& val)
  244. {
  245. insert_commit_data data;
  246. std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, val, data);
  247. if(ret.second){
  248. ret.first = priv_insert_commit(data, val);
  249. }
  250. return ret.first;
  251. }
  252. iterator insert_unique(const_iterator pos, BOOST_MOVE_MACRO_RV_REF(value_type) mval)
  253. {
  254. insert_commit_data data;
  255. std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, mval, data);
  256. if(ret.second){
  257. ret.first = priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(mval));
  258. }
  259. return ret.first;
  260. }
  261. iterator insert_equal(const_iterator pos, const value_type& val)
  262. {
  263. insert_commit_data data;
  264. priv_insert_equal_prepare(pos, val, data);
  265. return priv_insert_commit(data, val);
  266. }
  267. iterator insert_equal(const_iterator pos, BOOST_MOVE_MACRO_RV_REF(value_type) mval)
  268. {
  269. insert_commit_data data;
  270. priv_insert_equal_prepare(pos, mval, data);
  271. return priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(mval));
  272. }
  273. template <class InIt>
  274. void insert_unique(InIt first, InIt last)
  275. {
  276. for ( ; first != last; ++first)
  277. this->insert_unique(*first);
  278. }
  279. template <class InIt>
  280. void insert_equal(InIt first, InIt last)
  281. {
  282. typedef typename
  283. std::iterator_traits<InIt>::iterator_category ItCat;
  284. priv_insert_equal(first, last, ItCat());
  285. }
  286. #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
  287. template <class... Args>
  288. iterator emplace_unique(Args&&... args)
  289. {
  290. value_type && val = value_type(BOOST_CONTAINER_MOVE_NAMESPACE::forward<Args>(args)...);
  291. insert_commit_data data;
  292. std::pair<iterator,bool> ret =
  293. priv_insert_unique_prepare(val, data);
  294. if(ret.second){
  295. ret.first = priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(val));
  296. }
  297. return ret.first;
  298. }
  299. template <class... Args>
  300. iterator emplace_hint_unique(const_iterator hint, Args&&... args)
  301. {
  302. value_type && val = value_type(BOOST_CONTAINER_MOVE_NAMESPACE::forward<Args>(args)...);
  303. insert_commit_data data;
  304. std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
  305. if(ret.second){
  306. ret.first = priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(val));
  307. }
  308. return ret.first;
  309. }
  310. template <class... Args>
  311. iterator emplace_equal(Args&&... args)
  312. {
  313. value_type &&val = value_type(BOOST_CONTAINER_MOVE_NAMESPACE::forward<Args>(args)...);
  314. iterator i = this->upper_bound(KeyOfValue()(val));
  315. i = this->m_data.m_vect.insert(i, BOOST_CONTAINER_MOVE_NAMESPACE::move(val));
  316. return i;
  317. }
  318. template <class... Args>
  319. iterator emplace_hint_equal(const_iterator hint, Args&&... args)
  320. {
  321. value_type &&val = value_type(BOOST_CONTAINER_MOVE_NAMESPACE::forward<Args>(args)...);
  322. insert_commit_data data;
  323. priv_insert_equal_prepare(hint, val, data);
  324. return priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(val));
  325. }
  326. #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
  327. iterator emplace_unique()
  328. {
  329. containers_detail::value_init<value_type> vval;
  330. value_type &val = vval.m_t;
  331. insert_commit_data data;
  332. std::pair<iterator,bool> ret =
  333. priv_insert_unique_prepare(val, data);
  334. if(ret.second){
  335. ret.first = priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(val));
  336. }
  337. return ret.first;
  338. }
  339. iterator emplace_hint_unique(const_iterator hint)
  340. {
  341. containers_detail::value_init<value_type> vval;
  342. value_type &val = vval.m_t;
  343. insert_commit_data data;
  344. std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
  345. if(ret.second){
  346. ret.first = priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(val));
  347. }
  348. return ret.first;
  349. }
  350. iterator emplace_equal()
  351. {
  352. containers_detail::value_init<value_type> vval;
  353. value_type &val = vval.m_t;
  354. iterator i = this->upper_bound(KeyOfValue()(val));
  355. i = this->m_data.m_vect.insert(i, BOOST_CONTAINER_MOVE_NAMESPACE::move(val));
  356. return i;
  357. }
  358. iterator emplace_hint_equal(const_iterator hint)
  359. {
  360. containers_detail::value_init<value_type> vval;
  361. value_type &val = vval.m_t;
  362. insert_commit_data data;
  363. priv_insert_equal_prepare(hint, val, data);
  364. return priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(val));
  365. }
  366. #define BOOST_PP_LOCAL_MACRO(n) \
  367. template<BOOST_PP_ENUM_PARAMS(n, class P)> \
  368. iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
  369. { \
  370. value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
  371. insert_commit_data data; \
  372. std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
  373. if(ret.second){ \
  374. ret.first = priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(val)); \
  375. } \
  376. return ret.first; \
  377. } \
  378. \
  379. template<BOOST_PP_ENUM_PARAMS(n, class P)> \
  380. iterator emplace_hint_unique(const_iterator hint, \
  381. BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
  382. { \
  383. value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
  384. insert_commit_data data; \
  385. std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
  386. if(ret.second){ \
  387. ret.first = priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(val)); \
  388. } \
  389. return ret.first; \
  390. } \
  391. \
  392. template<BOOST_PP_ENUM_PARAMS(n, class P)> \
  393. iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
  394. { \
  395. value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
  396. iterator i = this->upper_bound(KeyOfValue()(val)); \
  397. i = this->m_data.m_vect.insert(i, BOOST_CONTAINER_MOVE_NAMESPACE::move(val)); \
  398. return i; \
  399. } \
  400. \
  401. template<BOOST_PP_ENUM_PARAMS(n, class P)> \
  402. iterator emplace_hint_equal(const_iterator hint, \
  403. BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
  404. { \
  405. value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
  406. insert_commit_data data; \
  407. priv_insert_equal_prepare(hint, val, data); \
  408. return priv_insert_commit(data, BOOST_CONTAINER_MOVE_NAMESPACE::move(val)); \
  409. } \
  410. //!
  411. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
  412. #include BOOST_PP_LOCAL_ITERATE()
  413. #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
  414. iterator erase(const_iterator position)
  415. { return this->m_data.m_vect.erase(position); }
  416. size_type erase(const key_type& k)
  417. {
  418. std::pair<iterator,iterator > itp = this->equal_range(k);
  419. size_type ret = static_cast<size_type>(itp.second-itp.first);
  420. if (ret){
  421. this->m_data.m_vect.erase(itp.first, itp.second);
  422. }
  423. return ret;
  424. }
  425. iterator erase(const_iterator first, const_iterator last)
  426. { return this->m_data.m_vect.erase(first, last); }
  427. void clear()
  428. { this->m_data.m_vect.clear(); }
  429. //! <b>Effects</b>: Tries to deallocate the excess of memory created
  430. // with previous allocations. The size of the vector is unchanged
  431. //!
  432. //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
  433. //!
  434. //! <b>Complexity</b>: Linear to size().
  435. void shrink_to_fit()
  436. { this->m_data.m_vect.shrink_to_fit(); }
  437. // set operations:
  438. iterator find(const key_type& k)
  439. {
  440. const Compare &key_comp = this->m_data.get_comp();
  441. iterator i = this->lower_bound(k);
  442. if (i != this->end() && key_comp(k, KeyOfValue()(*i))){
  443. i = this->end();
  444. }
  445. return i;
  446. }
  447. const_iterator find(const key_type& k) const
  448. {
  449. const Compare &key_comp = this->m_data.get_comp();
  450. const_iterator i = this->lower_bound(k);
  451. if (i != this->end() && key_comp(k, KeyOfValue()(*i))){
  452. i = this->end();
  453. }
  454. return i;
  455. }
  456. size_type count(const key_type& k) const
  457. {
  458. std::pair<const_iterator, const_iterator> p = this->equal_range(k);
  459. size_type n = p.second - p.first;
  460. return n;
  461. }
  462. iterator lower_bound(const key_type& k)
  463. { return this->priv_lower_bound(this->begin(), this->end(), k); }
  464. const_iterator lower_bound(const key_type& k) const
  465. { return this->priv_lower_bound(this->begin(), this->end(), k); }
  466. iterator upper_bound(const key_type& k)
  467. { return this->priv_upper_bound(this->begin(), this->end(), k); }
  468. const_iterator upper_bound(const key_type& k) const
  469. { return this->priv_upper_bound(this->begin(), this->end(), k); }
  470. std::pair<iterator,iterator> equal_range(const key_type& k)
  471. { return this->priv_equal_range(this->begin(), this->end(), k); }
  472. std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
  473. { return this->priv_equal_range(this->begin(), this->end(), k); }
  474. size_type capacity() const
  475. { return this->m_data.m_vect.capacity(); }
  476. void reserve(size_type count)
  477. { this->m_data.m_vect.reserve(count); }
  478. private:
  479. struct insert_commit_data
  480. {
  481. const_iterator position;
  482. };
  483. // insert/erase
  484. void priv_insert_equal_prepare
  485. (const_iterator pos, const value_type& val, insert_commit_data &data)
  486. {
  487. // N1780
  488. // To insert val at pos:
  489. // if pos == end || val <= *pos
  490. // if pos == begin || val >= *(pos-1)
  491. // insert val before pos
  492. // else
  493. // insert val before upper_bound(val)
  494. // else if pos+1 == end || val <= *(pos+1)
  495. // insert val after pos
  496. // else
  497. // insert val before lower_bound(val)
  498. const value_compare &value_comp = this->m_data;
  499. if(pos == this->cend() || !value_comp(*pos, val)){
  500. if (pos == this->cbegin() || !value_comp(val, pos[-1])){
  501. data.position = pos;
  502. }
  503. else{
  504. data.position =
  505. this->priv_upper_bound(this->cbegin(), pos, KeyOfValue()(val));
  506. }
  507. }
  508. //Works, but increases code complexity
  509. //else if (++pos == this->end() || !value_comp(*pos, val)){
  510. // return this->m_data.m_vect.insert(pos, val);
  511. //}
  512. else{
  513. data.position =
  514. this->priv_lower_bound(pos, this->cend(), KeyOfValue()(val));
  515. }
  516. }
  517. std::pair<iterator,bool> priv_insert_unique_prepare
  518. (const_iterator beg, const_iterator end, const value_type& val, insert_commit_data &commit_data)
  519. {
  520. const value_compare &value_comp = this->m_data;
  521. commit_data.position = this->priv_lower_bound(beg, end, KeyOfValue()(val));
  522. return std::pair<iterator,bool>
  523. ( *reinterpret_cast<iterator*>(&commit_data.position)
  524. , commit_data.position == end || value_comp(val, *commit_data.position));
  525. }
  526. std::pair<iterator,bool> priv_insert_unique_prepare
  527. (const value_type& val, insert_commit_data &commit_data)
  528. { return priv_insert_unique_prepare(this->begin(), this->end(), val, commit_data); }
  529. std::pair<iterator,bool> priv_insert_unique_prepare
  530. (const_iterator pos, const value_type& val, insert_commit_data &commit_data)
  531. {
  532. //N1780. Props to Howard Hinnant!
  533. //To insert val at pos:
  534. //if pos == end || val <= *pos
  535. // if pos == begin || val >= *(pos-1)
  536. // insert val before pos
  537. // else
  538. // insert val before upper_bound(val)
  539. //else if pos+1 == end || val <= *(pos+1)
  540. // insert val after pos
  541. //else
  542. // insert val before lower_bound(val)
  543. const value_compare &value_comp = this->m_data;
  544. if(pos == this->cend() || value_comp(val, *pos)){
  545. if(pos != this->cbegin() && !value_comp(val, pos[-1])){
  546. if(value_comp(pos[-1], val)){
  547. commit_data.position = pos;
  548. return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), true);
  549. }
  550. else{
  551. return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), false);
  552. }
  553. }
  554. return this->priv_insert_unique_prepare(this->cbegin(), pos, val, commit_data);
  555. }
  556. // Works, but increases code complexity
  557. //Next check
  558. //else if (value_comp(*pos, val) && !value_comp(pos[1], val)){
  559. // if(value_comp(val, pos[1])){
  560. // commit_data.position = pos+1;
  561. // return std::pair<iterator,bool>(pos+1, true);
  562. // }
  563. // else{
  564. // return std::pair<iterator,bool>(pos+1, false);
  565. // }
  566. //}
  567. else{
  568. //[... pos ... val ... ]
  569. //The hint is before the insertion position, so insert it
  570. //in the remaining range
  571. return this->priv_insert_unique_prepare(pos, this->end(), val, commit_data);
  572. }
  573. }
  574. template<class Convertible>
  575. iterator priv_insert_commit
  576. (insert_commit_data &commit_data, BOOST_MOVE_MACRO_FWD_REF(Convertible) convertible)
  577. {
  578. return this->m_data.m_vect.insert
  579. ( commit_data.position
  580. , BOOST_CONTAINER_MOVE_NAMESPACE::forward<Convertible>(convertible));
  581. }
  582. template <class RanIt>
  583. RanIt priv_lower_bound(RanIt first, RanIt last,
  584. const key_type & key) const
  585. {
  586. const Compare &key_comp = this->m_data.get_comp();
  587. KeyOfValue key_extract;
  588. difference_type len = last - first, half;
  589. RanIt middle;
  590. while (len > 0) {
  591. half = len >> 1;
  592. middle = first;
  593. middle += half;
  594. if (key_comp(key_extract(*middle), key)) {
  595. ++middle;
  596. first = middle;
  597. len = len - half - 1;
  598. }
  599. else
  600. len = half;
  601. }
  602. return first;
  603. }
  604. template <class RanIt>
  605. RanIt priv_upper_bound(RanIt first, RanIt last,
  606. const key_type & key) const
  607. {
  608. const Compare &key_comp = this->m_data.get_comp();
  609. KeyOfValue key_extract;
  610. difference_type len = last - first, half;
  611. RanIt middle;
  612. while (len > 0) {
  613. half = len >> 1;
  614. middle = first;
  615. middle += half;
  616. if (key_comp(key, key_extract(*middle))) {
  617. len = half;
  618. }
  619. else{
  620. first = ++middle;
  621. len = len - half - 1;
  622. }
  623. }
  624. return first;
  625. }
  626. template <class RanIt>
  627. std::pair<RanIt, RanIt>
  628. priv_equal_range(RanIt first, RanIt last, const key_type& key) const
  629. {
  630. const Compare &key_comp = this->m_data.get_comp();
  631. KeyOfValue key_extract;
  632. difference_type len = last - first, half;
  633. RanIt middle, left, right;
  634. while (len > 0) {
  635. half = len >> 1;
  636. middle = first;
  637. middle += half;
  638. if (key_comp(key_extract(*middle), key)){
  639. first = middle;
  640. ++first;
  641. len = len - half - 1;
  642. }
  643. else if (key_comp(key, key_extract(*middle))){
  644. len = half;
  645. }
  646. else {
  647. left = this->priv_lower_bound(first, middle, key);
  648. first += len;
  649. right = this->priv_upper_bound(++middle, first, key);
  650. return std::pair<RanIt, RanIt>(left, right);
  651. }
  652. }
  653. return std::pair<RanIt, RanIt>(first, first);
  654. }
  655. template <class FwdIt>
  656. void priv_insert_equal(FwdIt first, FwdIt last, std::forward_iterator_tag)
  657. {
  658. size_type len = static_cast<size_type>(std::distance(first, last));
  659. this->reserve(this->size()+len);
  660. this->priv_insert_equal(first, last, std::input_iterator_tag());
  661. }
  662. template <class InIt>
  663. void priv_insert_equal(InIt first, InIt last, std::input_iterator_tag)
  664. {
  665. for ( ; first != last; ++first)
  666. this->insert_equal(*first);
  667. }
  668. /*
  669. template <class FwdIt>
  670. void priv_insert_unique(FwdIt first, FwdIt last, std::forward_iterator_tag)
  671. {
  672. size_type len = static_cast<size_type>(std::distance(first, last));
  673. this->reserve(this->size()+len);
  674. priv_insert_unique(first, last, std::input_iterator_tag());
  675. }
  676. template <class InIt>
  677. void priv_insert_unique(InIt first, InIt last, std::input_iterator_tag)
  678. {
  679. for ( ; first != last; ++first)
  680. this->insert_unique(*first);
  681. }
  682. */
  683. };
  684. template <class Key, class Value, class KeyOfValue,
  685. class Compare, class Alloc>
  686. inline bool
  687. operator==(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
  688. const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
  689. {
  690. return x.size() == y.size() &&
  691. std::equal(x.begin(), x.end(), y.begin());
  692. }
  693. template <class Key, class Value, class KeyOfValue,
  694. class Compare, class Alloc>
  695. inline bool
  696. operator<(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
  697. const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
  698. {
  699. return std::lexicographical_compare(x.begin(), x.end(),
  700. y.begin(), y.end());
  701. }
  702. template <class Key, class Value, class KeyOfValue,
  703. class Compare, class Alloc>
  704. inline bool
  705. operator!=(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
  706. const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
  707. { return !(x == y); }
  708. template <class Key, class Value, class KeyOfValue,
  709. class Compare, class Alloc>
  710. inline bool
  711. operator>(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
  712. const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
  713. { return y < x; }
  714. template <class Key, class Value, class KeyOfValue,
  715. class Compare, class Alloc>
  716. inline bool
  717. operator<=(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
  718. const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
  719. { return !(y < x); }
  720. template <class Key, class Value, class KeyOfValue,
  721. class Compare, class Alloc>
  722. inline bool
  723. operator>=(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
  724. const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
  725. { return !(x < y); }
  726. template <class Key, class Value, class KeyOfValue,
  727. class Compare, class Alloc>
  728. inline void
  729. swap(flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
  730. flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
  731. { x.swap(y); }
  732. } //namespace containers_detail {
  733. } //namespace container {
  734. /*
  735. //!has_trivial_destructor_after_move<> == true_type
  736. //!specialization for optimizations
  737. template <class K, class V, class KOV,
  738. class C, class A>
  739. struct has_trivial_destructor_after_move<boost::container::containers_detail::flat_tree<K, V, KOV, C, A> >
  740. {
  741. static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
  742. };
  743. */
  744. } //namespace boost {
  745. #include INCLUDE_BOOST_CONTAINER_DETAIL_CONFIG_END_HPP
  746. #endif // BOOST_CONTAINERS_FLAT_TREE_HPP