aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2021-10-08 13:35:54 +0100
committerJonathan Wakely <jwakely@redhat.com>2021-10-09 00:57:47 +0100
commit64acc43de1e33616e43b239887a260eb4a51fcc7 (patch)
tree3ee405bdbd2670a548a32ebc2d3636e16bf1feb6 /libstdc++-v3
parent7afb61087d2cb7a6d27463bab5a7567fac69f97a (diff)
downloadgcc-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.h17
-rw-r--r--libstdc++-v3/include/bits/hashtable_policy.h9
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;