|
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> |
32 | 33 | #include <__type_traits/copy_cvref.h>
|
33 | 34 | #include <__type_traits/enable_if.h>
|
34 | 35 | #include <__type_traits/invoke.h>
|
|
45 | 46 | #include <__utility/move.h>
|
46 | 47 | #include <__utility/pair.h>
|
47 | 48 | #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,66 +797,40 @@ 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 | + |
800 | 818 | template <class... _Args>
|
801 | 819 | _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Args&&... __args) {
|
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)...); |
| 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)); |
860 | 834 | }
|
861 | 835 |
|
862 | 836 | template <class... _Args>
|
@@ -1025,8 +999,8 @@ private:
|
1025 | 999 | template <class... _Args>
|
1026 | 1000 | _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&&... __args);
|
1027 | 1001 |
|
1028 |
| - template <class... _Args> |
1029 |
| - _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _Args&&... __args); |
| 1002 | + template <class _First, class... _Rest> |
| 1003 | + _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest); |
1030 | 1004 |
|
1031 | 1005 | _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u) {
|
1032 | 1006 | __copy_assign_alloc(__u, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>());
|
@@ -1640,6 +1614,69 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(const_iterator __p
|
1640 | 1614 | return __node_insert_multi(__cp);
|
1641 | 1615 | }
|
1642 | 1616 |
|
| 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 | + |
1643 | 1680 | template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
1644 | 1681 | template <class... _Args>
|
1645 | 1682 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
|
@@ -1891,14 +1928,15 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) {
|
1891 | 1928 | }
|
1892 | 1929 |
|
1893 | 1930 | template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
1894 |
| -template <class... _Args> |
| 1931 | +template <class _First, class... _Rest> |
1895 | 1932 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
|
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"); |
| 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"); |
1898 | 1935 | __node_allocator& __na = __node_alloc();
|
1899 | 1936 | __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
|
1900 | 1937 | std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash);
|
1901 |
| - __node_traits::construct(__na, std::addressof(__h->__get_value()), std::forward<_Args>(__args)...); |
| 1938 | + __node_traits::construct( |
| 1939 | + __na, std::addressof(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...); |
1902 | 1940 | __h.get_deleter().__value_constructed = true;
|
1903 | 1941 | return __h;
|
1904 | 1942 | }
|
|
0 commit comments