-
Notifications
You must be signed in to change notification settings - Fork 15k
[libc++] Simplify __hash_table further #148375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37aad6e to
54023e4
Compare
54023e4 to
f1b949a
Compare
|
@llvm/pr-subscribers-libcxx Author: Nikolas Klauser (philnik777) ChangesFull diff: https://github.com/llvm/llvm-project/pull/148375.diff 3 Files Affected:
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 78f2f3bfd2f4c..03f50d9f3f269 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -122,6 +122,19 @@ struct __get_hash_node_value_type<__hash_value_type<_Key, _Tp> > {
template <class _Tp>
using __get_hash_node_value_type_t _LIBCPP_NODEBUG = typename __get_hash_node_value_type<_Tp>::type;
+template <class _Tp>
+struct __get_hash_node_key_type {
+ using type _LIBCPP_NODEBUG = _Tp;
+};
+
+template <class _Key, class _Tp>
+struct __get_hash_node_key_type<__hash_value_type<_Key, _Tp> > {
+ using type _LIBCPP_NODEBUG = _Key;
+};
+
+template <class _Tp>
+using __get_hash_node_key_type_t _LIBCPP_NODEBUG = typename __get_hash_node_key_type<_Tp>::type;
+
template <class _Tp, class _VoidPtr>
struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > > {
using __node_value_type _LIBCPP_NODEBUG = __get_hash_node_value_type_t<_Tp>;
@@ -182,69 +195,11 @@ class __hash_map_iterator;
template <class _HashIterator>
class __hash_map_const_iterator;
-template <class _Tp>
-struct __hash_key_value_types {
- static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, "");
- typedef _Tp key_type;
- typedef _Tp __node_value_type;
- typedef _Tp __container_value_type;
- static const bool __is_map = false;
-
- _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Tp const& __v) { return __v; }
- _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __v) { return __v; }
- _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { return std::addressof(__n); }
- _LIBCPP_HIDE_FROM_ABI static __container_value_type&& __move(__node_value_type& __v) { return std::move(__v); }
-};
-
-template <class _Key, class _Tp>
-struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
- typedef _Key key_type;
- typedef _Tp mapped_type;
- typedef __hash_value_type<_Key, _Tp> __node_value_type;
- typedef pair<const _Key, _Tp> __container_value_type;
- typedef __container_value_type __map_value_type;
- static const bool __is_map = true;
-
- _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__container_value_type const& __v) { return __v.first; }
-
- template <class _Up, __enable_if_t<is_same<__remove_cvref_t<_Up>, __node_value_type>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
- return __t.__get_value();
- }
-
- template <class _Up, __enable_if_t<is_same<__remove_cvref_t<_Up>, __container_value_type>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
- return __t;
- }
-
- _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__container_value_type& __n) {
- return std::addressof(__n);
- }
- _LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { return __v.__move(); }
-};
-
-template <class _Tp, class _AllocPtr, class _KVTypes = __hash_key_value_types<_Tp>, bool = _KVTypes::__is_map>
-struct __hash_map_pointer_types {};
-
-template <class _Tp, class _AllocPtr, class _KVTypes>
-struct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
- typedef typename _KVTypes::__map_value_type _Mv;
- typedef __rebind_pointer_t<_AllocPtr, _Mv> __map_value_type_pointer;
- typedef __rebind_pointer_t<_AllocPtr, const _Mv> __const_map_value_type_pointer;
-};
-
template <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
struct __hash_node_types;
template <class _NodePtr, class _Tp, class _VoidPtr>
-struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> >
- : public __hash_key_value_types<_Tp>,
- __hash_map_pointer_types<_Tp, _VoidPtr>
-
-{
- typedef __hash_key_value_types<_Tp> __base;
-
-public:
+struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> > {
typedef ptrdiff_t difference_type;
typedef size_t size_type;
@@ -617,8 +572,6 @@ public:
typedef typename __alloc_traits::pointer pointer;
private:
- typedef __hash_node_types<pointer> _NodeTypes;
-
allocator_type& __na_;
public:
@@ -633,7 +586,7 @@ public:
_LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT {
if (__value_constructed) {
- __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__get_value()));
+ __alloc_traits::destroy(__na_, std::addressof(__p->__get_value()));
std::__destroy_at(std::addressof(*__p));
}
if (__p)
@@ -684,6 +637,8 @@ template <class _Tp, class _Hash, class _Equal, class _Alloc>
class __hash_table {
public:
using value_type = __get_hash_node_value_type_t<_Tp>;
+ using key_type = __get_hash_node_key_type_t<_Tp>;
+
typedef _Hash hasher;
typedef _Equal key_equal;
typedef _Alloc allocator_type;
@@ -694,8 +649,6 @@ private:
public:
typedef typename _NodeTypes::__node_value_type __node_value_type;
- typedef typename _NodeTypes::__container_value_type __container_value_type;
- typedef typename _NodeTypes::key_type key_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef typename __alloc_traits::pointer pointer;
@@ -824,7 +777,7 @@ public:
template <class _First,
class _Second,
- __enable_if_t<__can_extract_map_key<_First, key_type, __container_value_type>::value, int> = 0>
+ __enable_if_t<__can_extract_map_key<_First, key_type, value_type>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_First&& __f, _Second&& __s) {
return __emplace_unique_key_args(__f, std::forward<_First>(__f), std::forward<_Second>(__s));
}
@@ -854,9 +807,7 @@ public:
template <class _ValueT = _Tp, __enable_if_t<__is_hash_value_type<_ValueT>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node(value_type&& __value) {
- using __key_type = typename _NodeTypes::key_type;
-
- __node_holder __h = __construct_node(const_cast<__key_type&&>(__value.first), std::move(__value.second));
+ __node_holder __h = __construct_node(const_cast<key_type&&>(__value.first), std::move(__value.second));
__node_insert_unique(__h.get());
__h.release();
}
@@ -870,9 +821,7 @@ public:
template <class _ValueT = _Tp, __enable_if_t<__is_hash_value_type<_ValueT>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(value_type&& __value) {
- using __key_type = typename _NodeTypes::key_type;
-
- __node_holder __h = __construct_node(const_cast<__key_type&&>(__value.first), std::move(__value.second));
+ __node_holder __h = __construct_node(const_cast<key_type&&>(__value.first), std::move(__value.second));
__node_insert_multi(__h.get());
__h.release();
}
@@ -1047,12 +996,10 @@ private:
template <class _From, class _ValueT = _Tp, __enable_if_t<__is_hash_value_type<_ValueT>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI void __assign_value(__get_hash_node_value_type_t<_Tp>& __lhs, _From&& __rhs) {
- using __key_type = typename _NodeTypes::key_type;
-
// This is technically UB, since the object was constructed as `const`.
// Clang doesn't optimize on this currently though.
- const_cast<__key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, __key_type>&&>(__rhs.first);
- __lhs.second = std::forward<_From>(__rhs).second;
+ const_cast<key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, key_type>&&>(__rhs.first);
+ __lhs.second = std::forward<_From>(__rhs).second;
}
template <class _From, class _ValueT = _Tp, __enable_if_t<!__is_hash_value_type<_ValueT>::value, int> = 0>
@@ -1201,7 +1148,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer
while (__np != nullptr) {
__next_pointer __next = __np->__next_;
__node_pointer __real_np = __np->__upcast();
- __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__get_value()));
+ __node_traits::destroy(__na, std::addressof(__real_np->__get_value()));
std::__destroy_at(std::addressof(*__real_np));
__node_traits::deallocate(__na, __real_np, 1);
__np = __next;
@@ -1290,8 +1237,8 @@ template <class _InputIterator>
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, _InputIterator __last) {
typedef iterator_traits<_InputIterator> _ITraits;
typedef typename _ITraits::value_type _ItValueType;
- static_assert(is_same<_ItValueType, __container_value_type>::value,
- "__assign_unique may only be called with the containers value type");
+ static_assert(
+ is_same<_ItValueType, value_type>::value, "__assign_unique may only be called with the containers value type");
if (bucket_count() != 0) {
__next_pointer __cache = __detach();
@@ -1321,10 +1268,8 @@ template <class _InputIterator>
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, _InputIterator __last) {
typedef iterator_traits<_InputIterator> _ITraits;
typedef typename _ITraits::value_type _ItValueType;
- static_assert(
- (is_same<_ItValueType, __container_value_type>::value || is_same<_ItValueType, __node_value_type>::value),
- "__assign_multi may only be called with the containers value type"
- " or the nodes value type");
+ static_assert(is_same<_ItValueType, value_type>::value,
+ "__assign_multi may only be called with the containers value type or the nodes value type");
if (bucket_count() != 0) {
__next_pointer __cache = __detach();
#if _LIBCPP_HAS_EXCEPTIONS
@@ -1345,7 +1290,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __f
__deallocate_node(__cache);
}
for (; __first != __last; ++__first)
- __emplace_multi(_NodeTypes::__get_value(*__first));
+ __emplace_multi(*__first);
}
template <class _Tp, class _Hash, class _Equal, class _Alloc>
@@ -1863,7 +1808,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) {
std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ 0);
// Now construct the value_type using the allocator's construct() method.
- __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_Args>(__args)...);
+ __node_traits::construct(__na, std::addressof(__h->__get_value()), std::forward<_Args>(__args)...);
__h.get_deleter().__value_constructed = true;
__h->__hash_ = hash_function()(__h->__get_value());
@@ -1879,7 +1824,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash);
__node_traits::construct(
- __na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...);
+ __na, std::addressof(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...);
__h.get_deleter().__value_constructed = true;
return __h;
}
diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map
index 5b70cdeae11a5..97c2c52eba337 100644
--- a/libcxx/include/unordered_map
+++ b/libcxx/include/unordered_map
@@ -844,10 +844,10 @@ class __hash_map_iterator {
public:
typedef forward_iterator_tag iterator_category;
- typedef typename _NodeTypes::__map_value_type value_type;
+ using value_type = typename _HashIterator::value_type;
typedef typename _NodeTypes::difference_type difference_type;
typedef value_type& reference;
- typedef typename _NodeTypes::__map_value_type_pointer pointer;
+ using pointer = typename _HashIterator::pointer;
_LIBCPP_HIDE_FROM_ABI __hash_map_iterator() _NOEXCEPT {}
@@ -895,10 +895,10 @@ class __hash_map_const_iterator {
public:
typedef forward_iterator_tag iterator_category;
- typedef typename _NodeTypes::__map_value_type value_type;
+ using value_type = typename _HashIterator::value_type;
typedef typename _NodeTypes::difference_type difference_type;
typedef const value_type& reference;
- typedef typename _NodeTypes::__const_map_value_type_pointer pointer;
+ using pointer = typename _HashIterator::pointer;
_LIBCPP_HIDE_FROM_ABI __hash_map_const_iterator() _NOEXCEPT {}
diff --git a/libcxx/test/libcxx/containers/unord/key_value_traits.pass.cpp b/libcxx/test/libcxx/containers/unord/key_value_traits.pass.cpp
deleted file mode 100644
index e00a028489a72..0000000000000
--- a/libcxx/test/libcxx/containers/unord/key_value_traits.pass.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// XFAIL: FROZEN-CXX03-HEADERS-FIXME
-
-#include <__hash_table>
-#include <unordered_map>
-#include <unordered_set>
-#include <type_traits>
-
-#include "test_macros.h"
-#include "min_allocator.h"
-
-void testKeyValueTrait() {
- {
- typedef int Tp;
- typedef std::__hash_key_value_types<Tp> Traits;
- static_assert((std::is_same<Traits::key_type, int>::value), "");
- static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
- static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
- static_assert(Traits::__is_map == false, "");
- }
- {
- typedef std::pair<int, int> Tp;
- typedef std::__hash_key_value_types<Tp> Traits;
- static_assert((std::is_same<Traits::key_type, Tp>::value), "");
- static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
- static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
- static_assert(Traits::__is_map == false, "");
- }
- {
- typedef std::pair<const int, int> Tp;
- typedef std::__hash_key_value_types<Tp> Traits;
- static_assert((std::is_same<Traits::key_type, Tp>::value), "");
- static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
- static_assert((std::is_same<Traits::__container_value_type, Tp>::value), "");
- static_assert(Traits::__is_map == false, "");
- }
- {
- typedef std::__hash_value_type<int, int> Tp;
- typedef std::__hash_key_value_types<Tp> Traits;
- static_assert((std::is_same<Traits::key_type, int>::value), "");
- static_assert((std::is_same<Traits::mapped_type, int>::value), "");
- static_assert((std::is_same<Traits::__node_value_type, Tp>::value), "");
- static_assert((std::is_same<Traits::__container_value_type, std::pair<const int, int> >::value), "");
- static_assert((std::is_same<Traits::__map_value_type, std::pair<const int, int> >::value), "");
- static_assert(Traits::__is_map == true, "");
- }
-}
-
-int main(int, char**) {
- testKeyValueTrait();
-
- return 0;
-}
|
ldionne
approved these changes
Jul 16, 2025
This was referenced Jul 23, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.