diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2021-10-08 13:35:54 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2021-10-09 00:57:47 +0100 |
commit | 64acc43de1e33616e43b239887a260eb4a51fcc7 (patch) | |
tree | 3ee405bdbd2670a548a32ebc2d3636e16bf1feb6 /libstdc++-v3 | |
parent | 7afb61087d2cb7a6d27463bab5a7567fac69f97a (diff) | |
download | gcc-64acc43de1e33616e43b239887a260eb4a51fcc7.zip gcc-64acc43de1e33616e43b239887a260eb4a51fcc7.tar.gz gcc-64acc43de1e33616e43b239887a260eb4a51fcc7.tar.bz2 |
libstdc++: Avoid instantiation of _Hash_node before it's needed
This is a step towards restoring support for incomplete types in
unordered containers (PR 53339).
We do not need to instantiate the node type to get its value_type
member, because we know that the value type is the first template
parameter. We can deduce that template argument using a custom trait and
a partial specialization for _Hash_node. If we wanted to support custom
hash node types we could still use typename _Tp::value_type in the
primary template of that trait, but that seems unnecessary.
The other change needed is to defer a static assert at class scope, so
that it is done when the types are complete. We must have a complete
type in the destructor, so we can do it there instead.
libstdc++-v3/ChangeLog:
* include/bits/hashtable.h: Move static assertion to destructor.
* include/bits/hashtable_policy.h: Deduce value type from node
type without instantiating it.
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/include/bits/hashtable.h | 17 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/hashtable_policy.h | 9 |
2 files changed, 17 insertions, 9 deletions
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index 79a3096..ff8af22 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -329,14 +329,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __hash_code_base_access : __hash_code_base { using __hash_code_base::_M_bucket_index; }; - // Getting a bucket index from a node shall not throw because it is used - // in methods (erase, swap...) that shall not throw. - static_assert(noexcept(declval<const __hash_code_base_access&>() - ._M_bucket_index(declval<const __node_value_type&>(), - (std::size_t)0)), - "Cache the hash code or qualify your functors involved" - " in hash code and bucket index computation with noexcept"); - // To get bucket index we need _RangeHash not to throw. static_assert(is_nothrow_default_constructible<_RangeHash>::value, "Functor used to map hash code to bucket index" @@ -1556,6 +1548,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>:: ~_Hashtable() noexcept { + // Getting a bucket index from a node shall not throw because it is used + // in methods (erase, swap...) that shall not throw. Need a complete + // type to check this, so do it in the destructor not at class scope. + static_assert(noexcept(declval<const __hash_code_base_access&>() + ._M_bucket_index(declval<const __node_value_type&>(), + (std::size_t)0)), + "Cache the hash code or qualify your functors involved" + " in hash code and bucket index computation with noexcept"); + clear(); _M_deallocate_buckets(); } diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h index 2f85025..75488da 100644 --- a/libstdc++-v3/include/bits/hashtable_policy.h +++ b/libstdc++-v3/include/bits/hashtable_policy.h @@ -1840,6 +1840,13 @@ namespace __detail { private: using __ebo_node_alloc = _Hashtable_ebo_helper<0, _NodeAlloc>; + + template<typename> + struct __get_value_type; + template<typename _Val, bool _Cache_hash_code> + struct __get_value_type<_Hash_node<_Val, _Cache_hash_code>> + { using type = _Val; }; + public: using __node_type = typename _NodeAlloc::value_type; using __node_alloc_type = _NodeAlloc; @@ -1847,7 +1854,7 @@ namespace __detail using __node_alloc_traits = __gnu_cxx::__alloc_traits<__node_alloc_type>; using __value_alloc_traits = typename __node_alloc_traits::template - rebind_traits<typename __node_type::value_type>; + rebind_traits<typename __get_value_type<__node_type>::type>; using __node_ptr = __node_type*; using __node_base = _Hash_node_base; |