|
29 | 29 | #include <__memory/swap_allocator.h>
|
30 | 30 | #include <__memory/unique_ptr.h>
|
31 | 31 | #include <__new/launder.h>
|
32 |
| -#include <__type_traits/can_extract_key.h> |
33 | 32 | #include <__type_traits/copy_cvref.h>
|
34 | 33 | #include <__type_traits/enable_if.h>
|
35 | 34 | #include <__type_traits/invoke.h>
|
|
46 | 45 | #include <__utility/move.h>
|
47 | 46 | #include <__utility/pair.h>
|
48 | 47 | #include <__utility/swap.h>
|
| 48 | +#include <__utility/try_key_extraction.h> |
49 | 49 | #include <limits>
|
50 | 50 |
|
51 | 51 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
@@ -797,40 +797,66 @@ public:
|
797 | 797 | _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(__node_pointer __nd);
|
798 | 798 | _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
|
799 | 799 |
|
800 |
| - template <class _Key, class... _Args> |
801 |
| - _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_key_args(_Key const& __k, _Args&&... __args); |
802 |
| - |
803 |
| - template <class... _Args> |
804 |
| - _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_impl(_Args&&... __args); |
805 |
| - |
806 |
| - template <class _Pp> |
807 |
| - _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Pp&& __x) { |
808 |
| - return __emplace_unique_extract_key(std::forward<_Pp>(__x), __can_extract_key<_Pp, key_type>()); |
809 |
| - } |
810 |
| - |
811 |
| - template <class _First, |
812 |
| - class _Second, |
813 |
| - __enable_if_t<__can_extract_map_key<_First, key_type, value_type>::value, int> = 0> |
814 |
| - _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_First&& __f, _Second&& __s) { |
815 |
| - return __emplace_unique_key_args(__f, std::forward<_First>(__f), std::forward<_Second>(__s)); |
816 |
| - } |
817 |
| - |
818 | 800 | template <class... _Args>
|
819 | 801 | _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Args&&... __args) {
|
820 |
| - return __emplace_unique_impl(std::forward<_Args>(__args)...); |
821 |
| - } |
822 |
| - |
823 |
| - template <class _Pp> |
824 |
| - _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) { |
825 |
| - return __emplace_unique_impl(std::forward<_Pp>(__x)); |
826 |
| - } |
827 |
| - template <class _Pp> |
828 |
| - _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) { |
829 |
| - return __emplace_unique_key_args(__x, std::forward<_Pp>(__x)); |
830 |
| - } |
831 |
| - template <class _Pp> |
832 |
| - _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) { |
833 |
| - return __emplace_unique_key_args(__x.first, std::forward<_Pp>(__x)); |
| 802 | + return std::__try_key_extraction<key_type>( |
| 803 | + [this](const key_type& __key, _Args&&... __args2) { |
| 804 | + size_t __hash = hash_function()(__key); |
| 805 | + size_type __bc = bucket_count(); |
| 806 | + bool __inserted = false; |
| 807 | + __next_pointer __nd; |
| 808 | + size_t __chash; |
| 809 | + if (__bc != 0) { |
| 810 | + __chash = std::__constrain_hash(__hash, __bc); |
| 811 | + __nd = __bucket_list_[__chash]; |
| 812 | + if (__nd != nullptr) { |
| 813 | + for (__nd = __nd->__next_; |
| 814 | + __nd != nullptr && |
| 815 | + (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash); |
| 816 | + __nd = __nd->__next_) { |
| 817 | + if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __key)) |
| 818 | + goto __done; |
| 819 | + } |
| 820 | + } |
| 821 | + } |
| 822 | + { |
| 823 | + __node_holder __h = __construct_node_hash(__hash, std::forward<_Args>(__args2)...); |
| 824 | + if (size() + 1 > __bc * max_load_factor() || __bc == 0) { |
| 825 | + __rehash_unique(std::max<size_type>(2 * __bc + !std::__is_hash_power2(__bc), |
| 826 | + size_type(__math::ceil(float(size() + 1) / max_load_factor())))); |
| 827 | + __bc = bucket_count(); |
| 828 | + __chash = std::__constrain_hash(__hash, __bc); |
| 829 | + } |
| 830 | + // insert_after __bucket_list_[__chash], or __first_node if bucket is null |
| 831 | + __next_pointer __pn = __bucket_list_[__chash]; |
| 832 | + if (__pn == nullptr) { |
| 833 | + __pn = __first_node_.__ptr(); |
| 834 | + __h->__next_ = __pn->__next_; |
| 835 | + __pn->__next_ = __h.get()->__ptr(); |
| 836 | + // fix up __bucket_list_ |
| 837 | + __bucket_list_[__chash] = __pn; |
| 838 | + if (__h->__next_ != nullptr) |
| 839 | + __bucket_list_[std::__constrain_hash(__h->__next_->__hash(), __bc)] = __h.get()->__ptr(); |
| 840 | + } else { |
| 841 | + __h->__next_ = __pn->__next_; |
| 842 | + __pn->__next_ = static_cast<__next_pointer>(__h.get()); |
| 843 | + } |
| 844 | + __nd = static_cast<__next_pointer>(__h.release()); |
| 845 | + // increment size |
| 846 | + ++size(); |
| 847 | + __inserted = true; |
| 848 | + } |
| 849 | + __done: |
| 850 | + return pair<iterator, bool>(iterator(__nd), __inserted); |
| 851 | + }, |
| 852 | + [this](_Args&&... __args2) { |
| 853 | + __node_holder __h = __construct_node(std::forward<_Args>(__args2)...); |
| 854 | + pair<iterator, bool> __r = __node_insert_unique(__h.get()); |
| 855 | + if (__r.second) |
| 856 | + __h.release(); |
| 857 | + return __r; |
| 858 | + }, |
| 859 | + std::forward<_Args>(__args)...); |
834 | 860 | }
|
835 | 861 |
|
836 | 862 | template <class... _Args>
|
@@ -999,8 +1025,8 @@ private:
|
999 | 1025 | template <class... _Args>
|
1000 | 1026 | _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&&... __args);
|
1001 | 1027 |
|
1002 |
| - template <class _First, class... _Rest> |
1003 |
| - _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest); |
| 1028 | + template <class... _Args> |
| 1029 | + _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _Args&&... __args); |
1004 | 1030 |
|
1005 | 1031 | _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u) {
|
1006 | 1032 | __copy_assign_alloc(__u, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>());
|
@@ -1614,69 +1640,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(const_iterator __p
|
1614 | 1640 | return __node_insert_multi(__cp);
|
1615 | 1641 | }
|
1616 | 1642 |
|
1617 |
| -template <class _Tp, class _Hash, class _Equal, class _Alloc> |
1618 |
| -template <class _Key, class... _Args> |
1619 |
| -pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool> |
1620 |
| -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) { |
1621 |
| - size_t __hash = hash_function()(__k); |
1622 |
| - size_type __bc = bucket_count(); |
1623 |
| - bool __inserted = false; |
1624 |
| - __next_pointer __nd; |
1625 |
| - size_t __chash; |
1626 |
| - if (__bc != 0) { |
1627 |
| - __chash = std::__constrain_hash(__hash, __bc); |
1628 |
| - __nd = __bucket_list_[__chash]; |
1629 |
| - if (__nd != nullptr) { |
1630 |
| - for (__nd = __nd->__next_; |
1631 |
| - __nd != nullptr && (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash); |
1632 |
| - __nd = __nd->__next_) { |
1633 |
| - if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k)) |
1634 |
| - goto __done; |
1635 |
| - } |
1636 |
| - } |
1637 |
| - } |
1638 |
| - { |
1639 |
| - __node_holder __h = __construct_node_hash(__hash, std::forward<_Args>(__args)...); |
1640 |
| - if (size() + 1 > __bc * max_load_factor() || __bc == 0) { |
1641 |
| - __rehash_unique(std::max<size_type>( |
1642 |
| - 2 * __bc + !std::__is_hash_power2(__bc), size_type(__math::ceil(float(size() + 1) / max_load_factor())))); |
1643 |
| - __bc = bucket_count(); |
1644 |
| - __chash = std::__constrain_hash(__hash, __bc); |
1645 |
| - } |
1646 |
| - // insert_after __bucket_list_[__chash], or __first_node if bucket is null |
1647 |
| - __next_pointer __pn = __bucket_list_[__chash]; |
1648 |
| - if (__pn == nullptr) { |
1649 |
| - __pn = __first_node_.__ptr(); |
1650 |
| - __h->__next_ = __pn->__next_; |
1651 |
| - __pn->__next_ = __h.get()->__ptr(); |
1652 |
| - // fix up __bucket_list_ |
1653 |
| - __bucket_list_[__chash] = __pn; |
1654 |
| - if (__h->__next_ != nullptr) |
1655 |
| - __bucket_list_[std::__constrain_hash(__h->__next_->__hash(), __bc)] = __h.get()->__ptr(); |
1656 |
| - } else { |
1657 |
| - __h->__next_ = __pn->__next_; |
1658 |
| - __pn->__next_ = static_cast<__next_pointer>(__h.get()); |
1659 |
| - } |
1660 |
| - __nd = static_cast<__next_pointer>(__h.release()); |
1661 |
| - // increment size |
1662 |
| - ++size(); |
1663 |
| - __inserted = true; |
1664 |
| - } |
1665 |
| -__done: |
1666 |
| - return pair<iterator, bool>(iterator(__nd), __inserted); |
1667 |
| -} |
1668 |
| - |
1669 |
| -template <class _Tp, class _Hash, class _Equal, class _Alloc> |
1670 |
| -template <class... _Args> |
1671 |
| -pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool> |
1672 |
| -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args) { |
1673 |
| - __node_holder __h = __construct_node(std::forward<_Args>(__args)...); |
1674 |
| - pair<iterator, bool> __r = __node_insert_unique(__h.get()); |
1675 |
| - if (__r.second) |
1676 |
| - __h.release(); |
1677 |
| - return __r; |
1678 |
| -} |
1679 |
| - |
1680 | 1643 | template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
1681 | 1644 | template <class... _Args>
|
1682 | 1645 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
|
@@ -1928,15 +1891,14 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) {
|
1928 | 1891 | }
|
1929 | 1892 |
|
1930 | 1893 | template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
1931 |
| -template <class _First, class... _Rest> |
| 1894 | +template <class... _Args> |
1932 | 1895 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
|
1933 |
| -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest) { |
1934 |
| - static_assert(!__is_hash_value_type<_First, _Rest...>::value, "Construct cannot be called with a hash value type"); |
| 1896 | +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _Args&&... __args) { |
| 1897 | + static_assert(!__is_hash_value_type<_Args...>::value, "Construct cannot be called with a hash value type"); |
1935 | 1898 | __node_allocator& __na = __node_alloc();
|
1936 | 1899 | __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
|
1937 | 1900 | std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash);
|
1938 |
| - __node_traits::construct( |
1939 |
| - __na, std::addressof(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...); |
| 1901 | + __node_traits::construct(__na, std::addressof(__h->__get_value()), std::forward<_Args>(__args)...); |
1940 | 1902 | __h.get_deleter().__value_constructed = true;
|
1941 | 1903 | return __h;
|
1942 | 1904 | }
|
|
0 commit comments