unordered_node_set.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. // Copyright (C) 2022-2023 Christian Mazakas
  2. // Copyright (C) 2024-2025 Joaquin M Lopez Munoz
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_UNORDERED_UNORDERED_NODE_SET_HPP_INCLUDED
  6. #define BOOST_UNORDERED_UNORDERED_NODE_SET_HPP_INCLUDED
  7. #include <boost/config.hpp>
  8. #if defined(BOOST_HAS_PRAGMA_ONCE)
  9. #pragma once
  10. #endif
  11. #include <boost/unordered/concurrent_node_set_fwd.hpp>
  12. #include <boost/unordered/detail/foa/element_type.hpp>
  13. #include <boost/unordered/detail/foa/node_set_handle.hpp>
  14. #include <boost/unordered/detail/foa/node_set_types.hpp>
  15. #include <boost/unordered/detail/foa/table.hpp>
  16. #include <boost/unordered/detail/serialize_container.hpp>
  17. #include <boost/unordered/detail/type_traits.hpp>
  18. #include <boost/unordered/unordered_node_set_fwd.hpp>
  19. #include <boost/core/allocator_access.hpp>
  20. #include <boost/container_hash/hash.hpp>
  21. #include <boost/throw_exception.hpp>
  22. #include <initializer_list>
  23. #include <iterator>
  24. #include <type_traits>
  25. #include <utility>
  26. namespace boost {
  27. namespace unordered {
  28. #if defined(BOOST_MSVC)
  29. #pragma warning(push)
  30. #pragma warning(disable : 4714) /* marked as __forceinline not inlined */
  31. #endif
  32. template <class Key, class Hash, class KeyEqual, class Allocator>
  33. class unordered_node_set
  34. {
  35. template <class Key2, class Hash2, class Pred2, class Allocator2>
  36. friend class concurrent_node_set;
  37. using set_types = detail::foa::node_set_types<Key,
  38. typename boost::allocator_void_pointer<Allocator>::type>;
  39. using table_type = detail::foa::table<set_types, Hash, KeyEqual,
  40. typename boost::allocator_rebind<Allocator,
  41. typename set_types::value_type>::type>;
  42. table_type table_;
  43. template <class K, class H, class KE, class A>
  44. bool friend operator==(unordered_node_set<K, H, KE, A> const& lhs,
  45. unordered_node_set<K, H, KE, A> const& rhs);
  46. template <class K, class H, class KE, class A, class Pred>
  47. typename unordered_node_set<K, H, KE, A>::size_type friend erase_if(
  48. unordered_node_set<K, H, KE, A>& set, Pred pred);
  49. public:
  50. using key_type = Key;
  51. using value_type = typename set_types::value_type;
  52. using init_type = typename set_types::init_type;
  53. using size_type = std::size_t;
  54. using difference_type = std::ptrdiff_t;
  55. using hasher = Hash;
  56. using key_equal = KeyEqual;
  57. using allocator_type = Allocator;
  58. using reference = value_type&;
  59. using const_reference = value_type const&;
  60. using pointer = typename boost::allocator_pointer<allocator_type>::type;
  61. using const_pointer =
  62. typename boost::allocator_const_pointer<allocator_type>::type;
  63. using iterator = typename table_type::iterator;
  64. using const_iterator = typename table_type::const_iterator;
  65. using node_type = detail::foa::node_set_handle<set_types,
  66. typename boost::allocator_rebind<Allocator,
  67. typename set_types::value_type>::type>;
  68. using insert_return_type =
  69. detail::foa::insert_return_type<iterator, node_type>;
  70. #if defined(BOOST_UNORDERED_ENABLE_STATS)
  71. using stats = typename table_type::stats;
  72. #endif
  73. unordered_node_set() : unordered_node_set(0) {}
  74. explicit unordered_node_set(size_type n, hasher const& h = hasher(),
  75. key_equal const& pred = key_equal(),
  76. allocator_type const& a = allocator_type())
  77. : table_(n, h, pred, a)
  78. {
  79. }
  80. unordered_node_set(size_type n, allocator_type const& a)
  81. : unordered_node_set(n, hasher(), key_equal(), a)
  82. {
  83. }
  84. unordered_node_set(size_type n, hasher const& h, allocator_type const& a)
  85. : unordered_node_set(n, h, key_equal(), a)
  86. {
  87. }
  88. template <class InputIterator>
  89. unordered_node_set(
  90. InputIterator f, InputIterator l, allocator_type const& a)
  91. : unordered_node_set(f, l, size_type(0), hasher(), key_equal(), a)
  92. {
  93. }
  94. explicit unordered_node_set(allocator_type const& a)
  95. : unordered_node_set(0, a)
  96. {
  97. }
  98. template <class Iterator>
  99. unordered_node_set(Iterator first, Iterator last, size_type n = 0,
  100. hasher const& h = hasher(), key_equal const& pred = key_equal(),
  101. allocator_type const& a = allocator_type())
  102. : unordered_node_set(n, h, pred, a)
  103. {
  104. this->insert(first, last);
  105. }
  106. template <class InputIt>
  107. unordered_node_set(
  108. InputIt first, InputIt last, size_type n, allocator_type const& a)
  109. : unordered_node_set(first, last, n, hasher(), key_equal(), a)
  110. {
  111. }
  112. template <class Iterator>
  113. unordered_node_set(Iterator first, Iterator last, size_type n,
  114. hasher const& h, allocator_type const& a)
  115. : unordered_node_set(first, last, n, h, key_equal(), a)
  116. {
  117. }
  118. unordered_node_set(unordered_node_set const& other) : table_(other.table_)
  119. {
  120. }
  121. unordered_node_set(
  122. unordered_node_set const& other, allocator_type const& a)
  123. : table_(other.table_, a)
  124. {
  125. }
  126. unordered_node_set(unordered_node_set&& other)
  127. noexcept(std::is_nothrow_move_constructible<table_type>::value)
  128. : table_(std::move(other.table_))
  129. {
  130. }
  131. unordered_node_set(unordered_node_set&& other, allocator_type const& al)
  132. : table_(std::move(other.table_), al)
  133. {
  134. }
  135. unordered_node_set(std::initializer_list<value_type> ilist,
  136. size_type n = 0, hasher const& h = hasher(),
  137. key_equal const& pred = key_equal(),
  138. allocator_type const& a = allocator_type())
  139. : unordered_node_set(ilist.begin(), ilist.end(), n, h, pred, a)
  140. {
  141. }
  142. unordered_node_set(
  143. std::initializer_list<value_type> il, allocator_type const& a)
  144. : unordered_node_set(il, size_type(0), hasher(), key_equal(), a)
  145. {
  146. }
  147. unordered_node_set(std::initializer_list<value_type> init, size_type n,
  148. allocator_type const& a)
  149. : unordered_node_set(init, n, hasher(), key_equal(), a)
  150. {
  151. }
  152. unordered_node_set(std::initializer_list<value_type> init, size_type n,
  153. hasher const& h, allocator_type const& a)
  154. : unordered_node_set(init, n, h, key_equal(), a)
  155. {
  156. }
  157. template <bool avoid_explicit_instantiation = true>
  158. unordered_node_set(
  159. concurrent_node_set<Key, Hash, KeyEqual, Allocator>&& other)
  160. : table_(std::move(other.table_))
  161. {
  162. }
  163. ~unordered_node_set() = default;
  164. unordered_node_set& operator=(unordered_node_set const& other)
  165. {
  166. table_ = other.table_;
  167. return *this;
  168. }
  169. unordered_node_set& operator=(unordered_node_set&& other) noexcept(
  170. noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
  171. {
  172. table_ = std::move(other.table_);
  173. return *this;
  174. }
  175. unordered_node_set& operator=(std::initializer_list<value_type> il)
  176. {
  177. this->clear();
  178. this->insert(il.begin(), il.end());
  179. return *this;
  180. }
  181. allocator_type get_allocator() const noexcept
  182. {
  183. return table_.get_allocator();
  184. }
  185. /// Iterators
  186. ///
  187. iterator begin() noexcept { return table_.begin(); }
  188. const_iterator begin() const noexcept { return table_.begin(); }
  189. const_iterator cbegin() const noexcept { return table_.cbegin(); }
  190. iterator end() noexcept { return table_.end(); }
  191. const_iterator end() const noexcept { return table_.end(); }
  192. const_iterator cend() const noexcept { return table_.cend(); }
  193. /// Capacity
  194. ///
  195. BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
  196. {
  197. return table_.empty();
  198. }
  199. size_type size() const noexcept { return table_.size(); }
  200. size_type max_size() const noexcept { return table_.max_size(); }
  201. /// Modifiers
  202. ///
  203. void clear() noexcept { table_.clear(); }
  204. BOOST_FORCEINLINE std::pair<iterator, bool> insert(
  205. value_type const& value)
  206. {
  207. return table_.insert(value);
  208. }
  209. BOOST_FORCEINLINE std::pair<iterator, bool> insert(value_type&& value)
  210. {
  211. return table_.insert(std::move(value));
  212. }
  213. template <class K>
  214. BOOST_FORCEINLINE typename std::enable_if<
  215. detail::transparent_non_iterable<K, unordered_node_set>::value,
  216. std::pair<iterator, bool> >::type
  217. insert(K&& k)
  218. {
  219. return table_.try_emplace(std::forward<K>(k));
  220. }
  221. BOOST_FORCEINLINE iterator insert(const_iterator, value_type const& value)
  222. {
  223. return table_.insert(value).first;
  224. }
  225. BOOST_FORCEINLINE iterator insert(const_iterator, value_type&& value)
  226. {
  227. return table_.insert(std::move(value)).first;
  228. }
  229. template <class K>
  230. BOOST_FORCEINLINE typename std::enable_if<
  231. detail::transparent_non_iterable<K, unordered_node_set>::value,
  232. iterator>::type
  233. insert(const_iterator, K&& k)
  234. {
  235. return table_.try_emplace(std::forward<K>(k)).first;
  236. }
  237. template <class InputIterator>
  238. void insert(InputIterator first, InputIterator last)
  239. {
  240. for (auto pos = first; pos != last; ++pos) {
  241. table_.emplace(*pos);
  242. }
  243. }
  244. void insert(std::initializer_list<value_type> ilist)
  245. {
  246. this->insert(ilist.begin(), ilist.end());
  247. }
  248. insert_return_type insert(node_type&& nh)
  249. {
  250. using access = detail::foa::node_handle_access;
  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(access::element(nh)));
  256. if (itp.second) {
  257. access::reset(nh);
  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. using access = detail::foa::node_handle_access;
  266. if (nh.empty()) {
  267. return end();
  268. }
  269. BOOST_ASSERT(get_allocator() == nh.get_allocator());
  270. auto itp = table_.insert(std::move(access::element(nh)));
  271. if (itp.second) {
  272. access::reset(nh);
  273. return itp.first;
  274. } else {
  275. return itp.first;
  276. }
  277. }
  278. template <class... Args>
  279. BOOST_FORCEINLINE std::pair<iterator, bool> emplace(Args&&... args)
  280. {
  281. return table_.emplace(std::forward<Args>(args)...);
  282. }
  283. template <class... Args>
  284. BOOST_FORCEINLINE iterator emplace_hint(const_iterator, Args&&... args)
  285. {
  286. return table_.emplace(std::forward<Args>(args)...).first;
  287. }
  288. BOOST_FORCEINLINE typename table_type::erase_return_type erase(
  289. const_iterator pos)
  290. {
  291. return table_.erase(pos);
  292. }
  293. iterator erase(const_iterator first, const_iterator last)
  294. {
  295. while (first != last) {
  296. this->erase(first++);
  297. }
  298. return iterator{detail::foa::const_iterator_cast_tag{}, last};
  299. }
  300. BOOST_FORCEINLINE size_type erase(key_type const& key)
  301. {
  302. return table_.erase(key);
  303. }
  304. template <class K>
  305. BOOST_FORCEINLINE typename std::enable_if<
  306. detail::transparent_non_iterable<K, unordered_node_set>::value,
  307. size_type>::type
  308. erase(K const& key)
  309. {
  310. return table_.erase(key);
  311. }
  312. BOOST_FORCEINLINE init_type pull(const_iterator pos)
  313. {
  314. return table_.pull(pos);
  315. }
  316. void swap(unordered_node_set& rhs) noexcept(
  317. noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
  318. {
  319. table_.swap(rhs.table_);
  320. }
  321. node_type extract(const_iterator pos)
  322. {
  323. BOOST_ASSERT(pos != end());
  324. node_type nh;
  325. auto elem = table_.extract(pos);
  326. detail::foa::node_handle_emplacer(nh)(
  327. std::move(elem), get_allocator());
  328. return nh;
  329. }
  330. node_type extract(key_type const& key)
  331. {
  332. auto pos = find(key);
  333. return pos != end() ? extract(pos) : node_type();
  334. }
  335. template <class K>
  336. typename std::enable_if<
  337. boost::unordered::detail::transparent_non_iterable<K,
  338. unordered_node_set>::value,
  339. node_type>::type
  340. extract(K const& key)
  341. {
  342. auto pos = find(key);
  343. return pos != end() ? extract(pos) : node_type();
  344. }
  345. template <class H2, class P2>
  346. void merge(unordered_node_set<key_type, H2, P2, allocator_type>& source)
  347. {
  348. BOOST_ASSERT(get_allocator() == source.get_allocator());
  349. table_.merge(source.table_);
  350. }
  351. template <class H2, class P2>
  352. void merge(unordered_node_set<key_type, H2, P2, allocator_type>&& source)
  353. {
  354. BOOST_ASSERT(get_allocator() == source.get_allocator());
  355. table_.merge(std::move(source.table_));
  356. }
  357. /// Lookup
  358. ///
  359. BOOST_FORCEINLINE size_type count(key_type const& key) const
  360. {
  361. auto pos = table_.find(key);
  362. return pos != table_.end() ? 1 : 0;
  363. }
  364. template <class K>
  365. BOOST_FORCEINLINE typename std::enable_if<
  366. detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
  367. count(K const& key) const
  368. {
  369. auto pos = table_.find(key);
  370. return pos != table_.end() ? 1 : 0;
  371. }
  372. BOOST_FORCEINLINE iterator find(key_type const& key)
  373. {
  374. return table_.find(key);
  375. }
  376. BOOST_FORCEINLINE const_iterator find(key_type const& key) const
  377. {
  378. return table_.find(key);
  379. }
  380. template <class K>
  381. BOOST_FORCEINLINE typename std::enable_if<
  382. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  383. iterator>::type
  384. find(K const& key)
  385. {
  386. return table_.find(key);
  387. }
  388. template <class K>
  389. BOOST_FORCEINLINE typename std::enable_if<
  390. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  391. const_iterator>::type
  392. find(K const& key) const
  393. {
  394. return table_.find(key);
  395. }
  396. BOOST_FORCEINLINE bool contains(key_type const& key) const
  397. {
  398. return this->find(key) != this->end();
  399. }
  400. template <class K>
  401. BOOST_FORCEINLINE typename std::enable_if<
  402. boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
  403. bool>::type
  404. contains(K const& key) const
  405. {
  406. return this->find(key) != this->end();
  407. }
  408. std::pair<iterator, iterator> equal_range(key_type const& key)
  409. {
  410. auto pos = table_.find(key);
  411. if (pos == table_.end()) {
  412. return {pos, pos};
  413. }
  414. auto next = pos;
  415. ++next;
  416. return {pos, next};
  417. }
  418. std::pair<const_iterator, const_iterator> equal_range(
  419. key_type const& key) const
  420. {
  421. auto pos = table_.find(key);
  422. if (pos == table_.end()) {
  423. return {pos, pos};
  424. }
  425. auto next = pos;
  426. ++next;
  427. return {pos, next};
  428. }
  429. template <class K>
  430. typename std::enable_if<
  431. detail::are_transparent<K, hasher, key_equal>::value,
  432. std::pair<iterator, iterator> >::type
  433. equal_range(K const& key)
  434. {
  435. auto pos = table_.find(key);
  436. if (pos == table_.end()) {
  437. return {pos, pos};
  438. }
  439. auto next = pos;
  440. ++next;
  441. return {pos, next};
  442. }
  443. template <class K>
  444. typename std::enable_if<
  445. detail::are_transparent<K, hasher, key_equal>::value,
  446. std::pair<const_iterator, const_iterator> >::type
  447. equal_range(K const& key) const
  448. {
  449. auto pos = table_.find(key);
  450. if (pos == table_.end()) {
  451. return {pos, pos};
  452. }
  453. auto next = pos;
  454. ++next;
  455. return {pos, next};
  456. }
  457. /// Hash Policy
  458. ///
  459. size_type bucket_count() const noexcept { return table_.capacity(); }
  460. float load_factor() const noexcept { return table_.load_factor(); }
  461. float max_load_factor() const noexcept
  462. {
  463. return table_.max_load_factor();
  464. }
  465. void max_load_factor(float) {}
  466. size_type max_load() const noexcept { return table_.max_load(); }
  467. void rehash(size_type n) { table_.rehash(n); }
  468. void reserve(size_type n) { table_.reserve(n); }
  469. #if defined(BOOST_UNORDERED_ENABLE_STATS)
  470. /// Stats
  471. ///
  472. stats get_stats() const { return table_.get_stats(); }
  473. void reset_stats() noexcept { table_.reset_stats(); }
  474. #endif
  475. /// Observers
  476. ///
  477. hasher hash_function() const { return table_.hash_function(); }
  478. key_equal key_eq() const { return table_.key_eq(); }
  479. };
  480. template <class Key, class Hash, class KeyEqual, class Allocator>
  481. bool operator==(
  482. unordered_node_set<Key, Hash, KeyEqual, Allocator> const& lhs,
  483. unordered_node_set<Key, Hash, KeyEqual, Allocator> const& rhs)
  484. {
  485. return lhs.table_ == rhs.table_;
  486. }
  487. template <class Key, class Hash, class KeyEqual, class Allocator>
  488. bool operator!=(
  489. unordered_node_set<Key, Hash, KeyEqual, Allocator> const& lhs,
  490. unordered_node_set<Key, Hash, KeyEqual, Allocator> const& rhs)
  491. {
  492. return !(lhs == rhs);
  493. }
  494. template <class Key, class Hash, class KeyEqual, class Allocator>
  495. void swap(unordered_node_set<Key, Hash, KeyEqual, Allocator>& lhs,
  496. unordered_node_set<Key, Hash, KeyEqual, Allocator>& rhs)
  497. noexcept(noexcept(lhs.swap(rhs)))
  498. {
  499. lhs.swap(rhs);
  500. }
  501. template <class Key, class Hash, class KeyEqual, class Allocator,
  502. class Pred>
  503. typename unordered_node_set<Key, Hash, KeyEqual, Allocator>::size_type
  504. erase_if(unordered_node_set<Key, Hash, KeyEqual, Allocator>& set, Pred pred)
  505. {
  506. return erase_if(set.table_, pred);
  507. }
  508. template <class Archive, class Key, class Hash, class KeyEqual,
  509. class Allocator>
  510. void serialize(Archive& ar,
  511. unordered_node_set<Key, Hash, KeyEqual, Allocator>& set,
  512. unsigned int version)
  513. {
  514. detail::serialize_container(ar, set, version);
  515. }
  516. #if defined(BOOST_MSVC)
  517. #pragma warning(pop) /* C4714 */
  518. #endif
  519. #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
  520. template <class InputIterator,
  521. class Hash =
  522. boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
  523. class Pred =
  524. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  525. class Allocator = std::allocator<
  526. typename std::iterator_traits<InputIterator>::value_type>,
  527. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  528. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  529. class = std::enable_if_t<detail::is_pred_v<Pred> >,
  530. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  531. unordered_node_set(InputIterator, InputIterator,
  532. std::size_t = boost::unordered::detail::foa::default_bucket_count,
  533. Hash = Hash(), Pred = Pred(), Allocator = Allocator())
  534. -> unordered_node_set<
  535. typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
  536. Allocator>;
  537. template <class T, class Hash = boost::hash<T>,
  538. class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
  539. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  540. class = std::enable_if_t<detail::is_pred_v<Pred> >,
  541. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  542. unordered_node_set(std::initializer_list<T>,
  543. std::size_t = boost::unordered::detail::foa::default_bucket_count,
  544. Hash = Hash(), Pred = Pred(), Allocator = Allocator())
  545. -> unordered_node_set<T, Hash, Pred, Allocator>;
  546. template <class InputIterator, class Allocator,
  547. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  548. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  549. unordered_node_set(InputIterator, InputIterator, std::size_t, Allocator)
  550. -> unordered_node_set<
  551. typename std::iterator_traits<InputIterator>::value_type,
  552. boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
  553. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  554. Allocator>;
  555. template <class InputIterator, class Hash, class Allocator,
  556. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  557. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  558. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  559. unordered_node_set(
  560. InputIterator, InputIterator, std::size_t, Hash, Allocator)
  561. -> unordered_node_set<
  562. typename std::iterator_traits<InputIterator>::value_type, Hash,
  563. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  564. Allocator>;
  565. template <class T, class Allocator,
  566. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  567. unordered_node_set(std::initializer_list<T>, std::size_t, Allocator)
  568. -> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
  569. template <class T, class Hash, class Allocator,
  570. class = std::enable_if_t<detail::is_hash_v<Hash> >,
  571. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  572. unordered_node_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
  573. -> unordered_node_set<T, Hash, std::equal_to<T>, Allocator>;
  574. template <class InputIterator, class Allocator,
  575. class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
  576. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  577. unordered_node_set(InputIterator, InputIterator, Allocator)
  578. -> unordered_node_set<
  579. typename std::iterator_traits<InputIterator>::value_type,
  580. boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
  581. std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
  582. Allocator>;
  583. template <class T, class Allocator,
  584. class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
  585. unordered_node_set(std::initializer_list<T>, Allocator)
  586. -> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
  587. #endif
  588. } // namespace unordered
  589. } // namespace boost
  590. #endif