unordered_node_map.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907
  1. // Copyright (C) 2022-2023 Christian Mazakas
  2. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  3. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. #ifndef BOOST_UNORDERED_UNORDERED_NODE_MAP_HPP_INCLUDED
  5. #define BOOST_UNORDERED_UNORDERED_NODE_MAP_HPP_INCLUDED
  6. #include <boost/config.hpp>
  7. #if defined(BOOST_HAS_PRAGMA_ONCE)
  8. #pragma once
  9. #endif
  10. #include <boost/unordered/detail/foa/element_type.hpp>
  11. #include <boost/unordered/detail/foa/node_handle.hpp>
  12. #include <boost/unordered/detail/foa/node_map_types.hpp>
  13. #include <boost/unordered/detail/foa/table.hpp>
  14. #include <boost/unordered/detail/serialize_container.hpp>
  15. #include <boost/unordered/detail/throw_exception.hpp>
  16. #include <boost/unordered/detail/type_traits.hpp>
  17. #include <boost/unordered/unordered_node_map_fwd.hpp>
  18. #include <boost/core/allocator_access.hpp>
  19. #include <boost/container_hash/hash.hpp>
  20. #include <initializer_list>
  21. #include <iterator>
  22. #include <stdexcept>
  23. #include <type_traits>
  24. #include <utility>
  25. namespace boost {
  26. namespace unordered {
  27. #if defined(BOOST_MSVC)
  28. #pragma warning(push)
  29. #pragma warning(disable : 4714) /* marked as __forceinline not inlined */
  30. #endif
  31. namespace detail {
  32. template <class TypePolicy, class Allocator>
  33. struct node_map_handle
  34. : public detail::foa::node_handle_base<TypePolicy, Allocator>
  35. {
  36. private:
  37. using base_type = detail::foa::node_handle_base<TypePolicy, Allocator>;
  38. using typename base_type::type_policy;
  39. template <class Key, class T, class Hash, class Pred, class Alloc>
  40. friend class boost::unordered::unordered_node_map;
  41. public:
  42. using key_type = typename TypePolicy::key_type;
  43. using mapped_type = typename TypePolicy::mapped_type;
  44. constexpr node_map_handle() noexcept = default;
  45. node_map_handle(node_map_handle&& nh) noexcept = default;
  46. node_map_handle& operator=(node_map_handle&&) noexcept = default;
  47. key_type& key() const
  48. {
  49. BOOST_ASSERT(!this->empty());
  50. return const_cast<key_type&>(this->data().first);
  51. }
  52. mapped_type& mapped() const
  53. {
  54. BOOST_ASSERT(!this->empty());
  55. return const_cast<mapped_type&>(this->data().second);
  56. }
  57. };
  58. } // namespace detail
  59. template <class Key, class T, class Hash, class KeyEqual, class Allocator>
  60. class unordered_node_map
  61. {
  62. using map_types = detail::foa::node_map_types<Key, T,
  63. typename boost::allocator_void_pointer<Allocator>::type>;
  64. using table_type = detail::foa::table<map_types, Hash, KeyEqual,
  65. typename boost::allocator_rebind<Allocator,
  66. std::pair<Key const, T> >::type>;
  67. table_type table_;
  68. template <class K, class V, class H, class KE, class A>
  69. bool friend operator==(unordered_node_map<K, V, H, KE, A> const& lhs,
  70. unordered_node_map<K, V, H, KE, A> const& rhs);
  71. template <class K, class V, class H, class KE, class A, class Pred>
  72. typename unordered_node_map<K, V, H, KE, A>::size_type friend erase_if(
  73. unordered_node_map<K, V, H, KE, A>& set, Pred pred);
  74. public:
  75. using key_type = Key;
  76. using mapped_type = T;
  77. using value_type = typename map_types::value_type;
  78. using init_type = typename map_types::init_type;
  79. using size_type = std::size_t;
  80. using difference_type = std::ptrdiff_t;
  81. using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
  82. using key_equal = typename boost::unordered::detail::type_identity<KeyEqual>::type;
  83. using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
  84. using reference = value_type&;
  85. using const_reference = value_type const&;
  86. using pointer = typename boost::allocator_pointer<allocator_type>::type;
  87. using const_pointer =
  88. typename boost::allocator_const_pointer<allocator_type>::type;
  89. using iterator = typename table_type::iterator;
  90. using const_iterator = typename table_type::const_iterator;
  91. using node_type = detail::node_map_handle<map_types,
  92. typename boost::allocator_rebind<Allocator,
  93. typename map_types::value_type>::type>;
  94. using insert_return_type =
  95. detail::foa::insert_return_type<iterator, node_type>;
  96. #if defined(BOOST_UNORDERED_ENABLE_STATS)
  97. using stats = typename table_type::stats;
  98. #endif
  99. unordered_node_map() : unordered_node_map(0) {}
  100. explicit unordered_node_map(size_type n, hasher const& h = hasher(),
  101. key_equal const& pred = key_equal(),
  102. allocator_type const& a = allocator_type())
  103. : table_(n, h, pred, a)
  104. {
  105. }
  106. unordered_node_map(size_type n, allocator_type const& a)
  107. : unordered_node_map(n, hasher(), key_equal(), a)
  108. {
  109. }
  110. unordered_node_map(size_type n, hasher const& h, allocator_type const& a)
  111. : unordered_node_map(n, h, key_equal(), a)
  112. {
  113. }
  114. template <class InputIterator>
  115. unordered_node_map(
  116. InputIterator f, InputIterator l, allocator_type const& a)
  117. : unordered_node_map(f, l, size_type(0), hasher(), key_equal(), a)
  118. {
  119. }
  120. explicit unordered_node_map(allocator_type const& a)
  121. : unordered_node_map(0, a)
  122. {
  123. }
  124. template <class Iterator>
  125. unordered_node_map(Iterator first, Iterator last, size_type n = 0,
  126. hasher const& h = hasher(), key_equal const& pred = key_equal(),
  127. allocator_type const& a = allocator_type())
  128. : unordered_node_map(n, h, pred, a)
  129. {
  130. this->insert(first, last);
  131. }
  132. template <class Iterator>
  133. unordered_node_map(
  134. Iterator first, Iterator last, size_type n, allocator_type const& a)
  135. : unordered_node_map(first, last, n, hasher(), key_equal(), a)
  136. {
  137. }
  138. template <class Iterator>
  139. unordered_node_map(Iterator first, Iterator last, size_type n,
  140. hasher const& h, allocator_type const& a)
  141. : unordered_node_map(first, last, n, h, key_equal(), a)
  142. {
  143. }
  144. unordered_node_map(unordered_node_map const& other) : table_(other.table_)
  145. {
  146. }
  147. unordered_node_map(
  148. unordered_node_map const& other, allocator_type const& a)
  149. : table_(other.table_, a)
  150. {
  151. }
  152. unordered_node_map(unordered_node_map&& other)
  153. noexcept(std::is_nothrow_move_constructible<table_type>::value)
  154. : table_(std::move(other.table_))
  155. {
  156. }
  157. unordered_node_map(unordered_node_map&& other, allocator_type const& al)
  158. : table_(std::move(other.table_), al)
  159. {
  160. }
  161. unordered_node_map(std::initializer_list<value_type> ilist,
  162. size_type n = 0, hasher const& h = hasher(),
  163. key_equal const& pred = key_equal(),
  164. allocator_type const& a = allocator_type())
  165. : unordered_node_map(ilist.begin(), ilist.end(), n, h, pred, a)
  166. {
  167. }
  168. unordered_node_map(
  169. std::initializer_list<value_type> il, allocator_type const& a)
  170. : unordered_node_map(il, size_type(0), hasher(), key_equal(), a)
  171. {
  172. }
  173. unordered_node_map(std::initializer_list<value_type> init, size_type n,
  174. allocator_type const& a)
  175. : unordered_node_map(init, n, hasher(), key_equal(), a)
  176. {
  177. }
  178. unordered_node_map(std::initializer_list<value_type> init, size_type n,
  179. hasher const& h, allocator_type const& a)
  180. : unordered_node_map(init, n, h, key_equal(), a)
  181. {
  182. }
  183. ~unordered_node_map() = default;
  184. unordered_node_map& operator=(unordered_node_map const& other)
  185. {
  186. table_ = other.table_;
  187. return *this;
  188. }
  189. unordered_node_map& operator=(unordered_node_map&& other) noexcept(
  190. noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
  191. {
  192. table_ = std::move(other.table_);
  193. return *this;
  194. }
  195. allocator_type get_allocator() const noexcept
  196. {
  197. return table_.get_allocator();
  198. }
  199. /// Iterators
  200. ///
  201. iterator begin() noexcept { return table_.begin(); }
  202. const_iterator begin() const noexcept { return table_.begin(); }
  203. const_iterator cbegin() const noexcept { return table_.cbegin(); }
  204. iterator end() noexcept { return table_.end(); }
  205. const_iterator end() const noexcept { return table_.end(); }
  206. const_iterator cend() const noexcept { return table_.cend(); }
  207. /// Capacity
  208. ///
  209. BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
  210. {
  211. return table_.empty();
  212. }
  213. size_type size() const noexcept { return table_.size(); }
  214. size_type max_size() const noexcept { return table_.max_size(); }
  215. /// Modifiers
  216. ///
  217. void clear() noexcept { table_.clear(); }
  218. template <class Ty>
  219. BOOST_FORCEINLINE auto insert(Ty&& value)
  220. -> decltype(table_.insert(std::forward<Ty>(value)))
  221. {
  222. return table_.insert(std::forward<Ty>(value));
  223. }
  224. BOOST_FORCEINLINE std::pair<iterator, bool> insert(init_type&& value)
  225. {
  226. return table_.insert(std::move(value));
  227. }
  228. template <class Ty>
  229. BOOST_FORCEINLINE auto insert(const_iterator, Ty&& value)
  230. -> decltype(table_.insert(std::forward<Ty>(value)).first)
  231. {
  232. return table_.insert(std::forward<Ty>(value)).first;
  233. }
  234. BOOST_FORCEINLINE iterator insert(const_iterator, init_type&& value)
  235. {
  236. return table_.insert(std::move(value)).first;
  237. }
  238. template <class InputIterator>
  239. BOOST_FORCEINLINE void insert(InputIterator first, InputIterator last)
  240. {
  241. for (auto pos = first; pos != last; ++pos) {
  242. table_.emplace(*pos);
  243. }
  244. }
  245. void insert(std::initializer_list<value_type> ilist)
  246. {
  247. this->insert(ilist.begin(), ilist.end());
  248. }
  249. insert_return_type insert(node_type&& nh)
  250. {
  251. if (nh.empty()) {
  252. return {end(), false, node_type{}};
  253. }
  254. BOOST_ASSERT(get_allocator() == nh.get_allocator());
  255. auto itp = table_.insert(std::move(nh.element()));
  256. if (itp.second) {
  257. nh.reset();
  258. return {itp.first, true, node_type{}};
  259. } else {
  260. return {itp.first, false, std::move(nh)};
  261. }
  262. }
  263. iterator insert(const_iterator, node_type&& nh)
  264. {
  265. if (nh.empty()) {
  266. return end();
  267. }
  268. BOOST_ASSERT(get_allocator() == nh.get_allocator());
  269. auto itp = table_.insert(std::move(nh.element()));
  270. if (itp.second) {
  271. nh.reset();
  272. return itp.first;
  273. } else {
  274. return itp.first;
  275. }
  276. }
  277. template <class M>
  278. std::pair<iterator, bool> insert_or_assign(key_type const& key, M&& obj)
  279. {
  280. auto ibp = table_.try_emplace(key, std::forward<M>(obj));
  281. if (ibp.second) {
  282. return ibp;
  283. }
  284. ibp.first->second = std::forward<M>(obj);
  285. return ibp;
  286. }
  287. template <class M>
  288. std::pair<iterator, bool> insert_or_assign(key_type&& key, M&& obj)
  289. {
  290. auto ibp = table_.try_emplace(std::move(key), std::forward<M>(obj));
  291. if (ibp.second) {
  292. return ibp;
  293. }
  294. ibp.first->second = std::forward<M>(obj);
  295. return ibp;
  296. }
  297. template <class K, class M>
  298. typename std::enable_if<
  299. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  300. std::pair<iterator, bool> >::type
  301. insert_or_assign(K&& k, M&& obj)
  302. {
  303. auto ibp = table_.try_emplace(std::forward<K>(k), std::forward<M>(obj));
  304. if (ibp.second) {
  305. return ibp;
  306. }
  307. ibp.first->second = std::forward<M>(obj);
  308. return ibp;
  309. }
  310. template <class M>
  311. iterator insert_or_assign(const_iterator, key_type const& key, M&& obj)
  312. {
  313. return this->insert_or_assign(key, std::forward<M>(obj)).first;
  314. }
  315. template <class M>
  316. iterator insert_or_assign(const_iterator, key_type&& key, M&& obj)
  317. {
  318. return this->insert_or_assign(std::move(key), std::forward<M>(obj))
  319. .first;
  320. }
  321. template <class K, class M>
  322. typename std::enable_if<
  323. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  324. iterator>::type
  325. insert_or_assign(const_iterator, K&& k, M&& obj)
  326. {
  327. return this->insert_or_assign(std::forward<K>(k), std::forward<M>(obj))
  328. .first;
  329. }
  330. template <class... Args>
  331. BOOST_FORCEINLINE std::pair<iterator, bool> emplace(Args&&... args)
  332. {
  333. return table_.emplace(std::forward<Args>(args)...);
  334. }
  335. template <class... Args>
  336. BOOST_FORCEINLINE iterator emplace_hint(const_iterator, Args&&... args)
  337. {
  338. return table_.emplace(std::forward<Args>(args)...).first;
  339. }
  340. template <class... Args>
  341. BOOST_FORCEINLINE std::pair<iterator, bool> try_emplace(
  342. key_type const& key, Args&&... args)
  343. {
  344. return table_.try_emplace(key, std::forward<Args>(args)...);
  345. }
  346. template <class... Args>
  347. BOOST_FORCEINLINE std::pair<iterator, bool> try_emplace(
  348. key_type&& key, Args&&... args)
  349. {
  350. return table_.try_emplace(std::move(key), std::forward<Args>(args)...);
  351. }
  352. template <class K, class... Args>
  353. BOOST_FORCEINLINE typename std::enable_if<
  354. boost::unordered::detail::transparent_non_iterable<K,
  355. unordered_node_map>::value,
  356. std::pair<iterator, bool> >::type
  357. try_emplace(K&& key, Args&&... args)
  358. {
  359. return table_.try_emplace(
  360. std::forward<K>(key), std::forward<Args>(args)...);
  361. }
  362. template <class... Args>
  363. BOOST_FORCEINLINE iterator try_emplace(
  364. const_iterator, key_type const& key, Args&&... args)
  365. {
  366. return table_.try_emplace(key, std::forward<Args>(args)...).first;
  367. }
  368. template <class... Args>
  369. BOOST_FORCEINLINE iterator try_emplace(
  370. const_iterator, key_type&& key, Args&&... args)
  371. {
  372. return table_.try_emplace(std::move(key), std::forward<Args>(args)...)
  373. .first;
  374. }
  375. template <class K, class... Args>
  376. BOOST_FORCEINLINE typename std::enable_if<
  377. boost::unordered::detail::transparent_non_iterable<K,
  378. unordered_node_map>::value,
  379. iterator>::type
  380. try_emplace(const_iterator, K&& key, Args&&... args)
  381. {
  382. return table_
  383. .try_emplace(std::forward<K>(key), std::forward<Args>(args)...)
  384. .first;
  385. }
  386. BOOST_FORCEINLINE typename table_type::erase_return_type erase(
  387. iterator pos)
  388. {
  389. return table_.erase(pos);
  390. }
  391. BOOST_FORCEINLINE typename table_type::erase_return_type erase(
  392. const_iterator pos)
  393. {
  394. return table_.erase(pos);
  395. }
  396. iterator erase(const_iterator first, const_iterator last)
  397. {
  398. while (first != last) {
  399. this->erase(first++);
  400. }
  401. return iterator{detail::foa::const_iterator_cast_tag{}, last};
  402. }
  403. BOOST_FORCEINLINE size_type erase(key_type const& key)
  404. {
  405. return table_.erase(key);
  406. }
  407. template <class K>
  408. BOOST_FORCEINLINE typename std::enable_if<
  409. detail::transparent_non_iterable<K, unordered_node_map>::value,
  410. size_type>::type
  411. erase(K const& key)
  412. {
  413. return table_.erase(key);
  414. }
  415. void swap(unordered_node_map& rhs) noexcept(
  416. noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
  417. {
  418. table_.swap(rhs.table_);
  419. }
  420. node_type extract(const_iterator pos)
  421. {
  422. BOOST_ASSERT(pos != end());
  423. node_type nh;
  424. auto elem = table_.extract(pos);
  425. nh.emplace(std::move(elem), get_allocator());
  426. return nh;
  427. }
  428. node_type extract(key_type const& key)
  429. {
  430. auto pos = find(key);
  431. return pos != end() ? extract(pos) : node_type();
  432. }
  433. template <class K>
  434. typename std::enable_if<
  435. boost::unordered::detail::transparent_non_iterable<K,
  436. unordered_node_map>::value,
  437. node_type>::type
  438. extract(K const& key)
  439. {
  440. auto pos = find(key);
  441. return pos != end() ? extract(pos) : node_type();
  442. }
  443. template <class H2, class P2>
  444. void merge(
  445. unordered_node_map<key_type, mapped_type, H2, P2, allocator_type>&
  446. source)
  447. {
  448. BOOST_ASSERT(get_allocator() == source.get_allocator());
  449. table_.merge(source.table_);
  450. }
  451. template <class H2, class P2>
  452. void merge(
  453. unordered_node_map<key_type, mapped_type, H2, P2, allocator_type>&&
  454. source)
  455. {
  456. BOOST_ASSERT(get_allocator() == source.get_allocator());
  457. table_.merge(std::move(source.table_));
  458. }
  459. /// Lookup
  460. ///
  461. mapped_type& at(key_type const& key)
  462. {
  463. auto pos = table_.find(key);
  464. if (pos != table_.end()) {
  465. return pos->second;
  466. }
  467. // TODO: someday refactor this to conditionally serialize the key and
  468. // include it in the error message
  469. //
  470. boost::unordered::detail::throw_out_of_range(
  471. "key was not found in unordered_node_map");
  472. }
  473. mapped_type const& at(key_type const& key) const
  474. {
  475. auto pos = table_.find(key);
  476. if (pos != table_.end()) {
  477. return pos->second;
  478. }
  479. boost::unordered::detail::throw_out_of_range(
  480. "key was not found in unordered_node_map");
  481. }
  482. template <class K>
  483. typename std::enable_if<
  484. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  485. mapped_type&>::type
  486. at(K&& key)
  487. {
  488. auto pos = table_.find(std::forward<K>(key));
  489. if (pos != table_.end()) {
  490. return pos->second;
  491. }
  492. boost::unordered::detail::throw_out_of_range(
  493. "key was not found in unordered_node_map");
  494. }
  495. template <class K>
  496. typename std::enable_if<
  497. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  498. mapped_type const&>::type
  499. at(K&& key) const
  500. {
  501. auto pos = table_.find(std::forward<K>(key));
  502. if (pos != table_.end()) {
  503. return pos->second;
  504. }
  505. boost::unordered::detail::throw_out_of_range(
  506. "key was not found in unordered_node_map");
  507. }
  508. BOOST_FORCEINLINE mapped_type& operator[](key_type const& key)
  509. {
  510. return table_.try_emplace(key).first->second;
  511. }
  512. BOOST_FORCEINLINE mapped_type& operator[](key_type&& key)
  513. {
  514. return table_.try_emplace(std::move(key)).first->second;
  515. }
  516. template <class K>
  517. typename std::enable_if<
  518. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  519. mapped_type&>::type
  520. operator[](K&& key)
  521. {
  522. return table_.try_emplace(std::forward<K>(key)).first->second;
  523. }
  524. BOOST_FORCEINLINE size_type count(key_type const& key) const
  525. {
  526. auto pos = table_.find(key);
  527. return pos != table_.end() ? 1 : 0;
  528. }
  529. template <class K>
  530. BOOST_FORCEINLINE typename std::enable_if<
  531. detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
  532. count(K const& key) const
  533. {
  534. auto pos = table_.find(key);
  535. return pos != table_.end() ? 1 : 0;
  536. }
  537. BOOST_FORCEINLINE iterator find(key_type const& key)
  538. {
  539. return table_.find(key);
  540. }
  541. BOOST_FORCEINLINE const_iterator find(key_type const& key) const
  542. {
  543. return table_.find(key);
  544. }
  545. template <class K>
  546. BOOST_FORCEINLINE typename std::enable_if<
  547. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  548. iterator>::type
  549. find(K const& key)
  550. {
  551. return table_.find(key);
  552. }
  553. template <class K>
  554. BOOST_FORCEINLINE typename std::enable_if<
  555. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  556. const_iterator>::type
  557. find(K const& key) const
  558. {
  559. return table_.find(key);
  560. }
  561. BOOST_FORCEINLINE bool contains(key_type const& key) const
  562. {
  563. return this->find(key) != this->end();
  564. }
  565. template <class K>
  566. BOOST_FORCEINLINE typename std::enable_if<
  567. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  568. bool>::type
  569. contains(K const& key) const
  570. {
  571. return this->find(key) != this->end();
  572. }
  573. std::pair<iterator, iterator> equal_range(key_type const& key)
  574. {
  575. auto pos = table_.find(key);
  576. if (pos == table_.end()) {
  577. return {pos, pos};
  578. }
  579. auto next = pos;
  580. ++next;
  581. return {pos, next};
  582. }
  583. std::pair<const_iterator, const_iterator> equal_range(
  584. key_type const& key) const
  585. {
  586. auto pos = table_.find(key);
  587. if (pos == table_.end()) {
  588. return {pos, pos};
  589. }
  590. auto next = pos;
  591. ++next;
  592. return {pos, next};
  593. }
  594. template <class K>
  595. typename std::enable_if<
  596. detail::are_transparent<K, hasher, key_equal>::value,
  597. std::pair<iterator, iterator> >::type
  598. equal_range(K const& key)
  599. {
  600. auto pos = table_.find(key);
  601. if (pos == table_.end()) {
  602. return {pos, pos};
  603. }
  604. auto next = pos;
  605. ++next;
  606. return {pos, next};
  607. }
  608. template <class K>
  609. typename std::enable_if<
  610. detail::are_transparent<K, hasher, key_equal>::value,
  611. std::pair<const_iterator, const_iterator> >::type
  612. equal_range(K const& key) const
  613. {
  614. auto pos = table_.find(key);
  615. if (pos == table_.end()) {
  616. return {pos, pos};
  617. }
  618. auto next = pos;
  619. ++next;
  620. return {pos, next};
  621. }
  622. /// Hash Policy
  623. ///
  624. size_type bucket_count() const noexcept { return table_.capacity(); }
  625. float load_factor() const noexcept { return table_.load_factor(); }
  626. float max_load_factor() const noexcept
  627. {
  628. return table_.max_load_factor();
  629. }
  630. void max_load_factor(float) {}
  631. size_type max_load() const noexcept { return table_.max_load(); }
  632. void rehash(size_type n) { table_.rehash(n); }
  633. void reserve(size_type n) { table_.reserve(n); }
  634. #if defined(BOOST_UNORDERED_ENABLE_STATS)
  635. /// Stats
  636. ///
  637. stats get_stats() const { return table_.get_stats(); }
  638. void reset_stats() noexcept { table_.reset_stats(); }
  639. #endif
  640. /// Observers
  641. ///
  642. hasher hash_function() const { return table_.hash_function(); }
  643. key_equal key_eq() const { return table_.key_eq(); }
  644. };
  645. template <class Key, class T, class Hash, class KeyEqual, class Allocator>
  646. bool operator==(
  647. unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
  648. unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& rhs)
  649. {
  650. return lhs.table_ == rhs.table_;
  651. }
  652. template <class Key, class T, class Hash, class KeyEqual, class Allocator>
  653. bool operator!=(
  654. unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
  655. unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& rhs)
  656. {
  657. return !(lhs == rhs);
  658. }
  659. template <class Key, class T, class Hash, class KeyEqual, class Allocator>
  660. void swap(unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
  661. unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
  662. noexcept(noexcept(lhs.swap(rhs)))
  663. {
  664. lhs.swap(rhs);
  665. }
  666. template <class Key, class T, class Hash, class KeyEqual, class Allocator,
  667. class Pred>
  668. typename unordered_node_map<Key, T, Hash, KeyEqual, Allocator>::size_type
  669. erase_if(
  670. unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& map, Pred pred)
  671. {
  672. return erase_if(map.table_, pred);
  673. }
  674. template <class Archive, class Key, class T, class Hash, class KeyEqual,
  675. class Allocator>
  676. void serialize(Archive& ar,
  677. unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& map,
  678. unsigned int version)
  679. {
  680. detail::serialize_container(ar, map, version);
  681. }
  682. #if defined(BOOST_MSVC)
  683. #pragma warning(pop) /* C4714 */
  684. #endif
  685. #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
  686. template <class InputIterator,
  687. class Hash =
  688. boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
  689. class Pred =
  690. std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
  691. class Allocator = std::allocator<
  692. boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
  693. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  694. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  695. class = std::enable_if_t<detail::is_pred_v<Pred> >,
  696. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  697. unordered_node_map(InputIterator, InputIterator,
  698. std::size_t = boost::unordered::detail::foa::default_bucket_count,
  699. Hash = Hash(), Pred = Pred(), Allocator = Allocator())
  700. -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
  701. boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
  702. Allocator>;
  703. template <class Key, class T,
  704. class Hash = boost::hash<std::remove_const_t<Key> >,
  705. class Pred = std::equal_to<std::remove_const_t<Key> >,
  706. class Allocator = std::allocator<std::pair<const Key, T> >,
  707. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  708. class = std::enable_if_t<detail::is_pred_v<Pred> >,
  709. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  710. unordered_node_map(std::initializer_list<std::pair<Key, T> >,
  711. std::size_t = boost::unordered::detail::foa::default_bucket_count,
  712. Hash = Hash(), Pred = Pred(), Allocator = Allocator())
  713. -> unordered_node_map<std::remove_const_t<Key>, T, Hash, Pred,
  714. Allocator>;
  715. template <class InputIterator, class Allocator,
  716. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  717. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  718. unordered_node_map(InputIterator, InputIterator, std::size_t, Allocator)
  719. -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
  720. boost::unordered::detail::iter_val_t<InputIterator>,
  721. boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
  722. std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
  723. Allocator>;
  724. template <class InputIterator, class Allocator,
  725. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  726. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  727. unordered_node_map(InputIterator, InputIterator, Allocator)
  728. -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
  729. boost::unordered::detail::iter_val_t<InputIterator>,
  730. boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
  731. std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
  732. Allocator>;
  733. template <class InputIterator, class Hash, class Allocator,
  734. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  735. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  736. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  737. unordered_node_map(
  738. InputIterator, InputIterator, std::size_t, Hash, Allocator)
  739. -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
  740. boost::unordered::detail::iter_val_t<InputIterator>, Hash,
  741. std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
  742. Allocator>;
  743. template <class Key, class T, class Allocator,
  744. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  745. unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
  746. Allocator) -> unordered_node_map<std::remove_const_t<Key>, T,
  747. boost::hash<std::remove_const_t<Key> >,
  748. std::equal_to<std::remove_const_t<Key> >, Allocator>;
  749. template <class Key, class T, class Allocator,
  750. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  751. unordered_node_map(std::initializer_list<std::pair<Key, T> >, Allocator)
  752. -> unordered_node_map<std::remove_const_t<Key>, T,
  753. boost::hash<std::remove_const_t<Key> >,
  754. std::equal_to<std::remove_const_t<Key> >, Allocator>;
  755. template <class Key, class T, class Hash, class Allocator,
  756. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  757. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  758. unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
  759. Hash, Allocator) -> unordered_node_map<std::remove_const_t<Key>, T,
  760. Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
  761. #endif
  762. } // namespace unordered
  763. } // namespace boost
  764. #endif