2 //===----------------------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #ifndef SUPPORT_POISONED_HASH_HELPER_H
11 #define SUPPORT_POISONED_HASH_HELPER_H
16 #include <type_traits>
19 #include "test_macros.h"
20 #include "type_algorithms.h"
22 template <class Hash
, class Key
, class Res
= decltype(std::declval
<Hash
&>()(std::declval
<Key
>()))>
23 constexpr bool can_hash_impl(int) {
24 return std::is_same
<Res
, std::size_t>::value
;
26 template <class, class>
27 constexpr bool can_hash_impl(long) {
30 template <class Hash
, class Key
>
31 constexpr bool can_hash() {
32 return can_hash_impl
<Hash
, Key
>(0);
36 struct ConvertibleToSimple
{
37 operator To() const { return To
{}; }
41 struct ConvertibleTo
{
43 operator To
&() & { return to
; }
44 operator To
const&() const& { return to
; }
45 operator To
&&() && { return std::move(to
); }
46 operator To
const&&() const&& { return std::move(to
); }
49 // Test that the specified Hash meets the requirements of an enabled hash
50 template <class Key
, class Hash
= std::hash
<Key
>>
51 TEST_CONSTEXPR_CXX20
void test_hash_enabled(Key
const& key
= Key
{}) {
52 static_assert(std::is_destructible
<Hash
>::value
, "");
54 // Enabled hash requirements
55 static_assert(std::is_default_constructible
<Hash
>::value
, "");
56 static_assert(std::is_copy_constructible
<Hash
>::value
, "");
57 static_assert(std::is_move_constructible
<Hash
>::value
, "");
58 static_assert(std::is_copy_assignable
<Hash
>::value
, "");
59 static_assert(std::is_move_assignable
<Hash
>::value
, "");
62 static_assert(std::is_swappable
<Hash
>::value
, "");
63 #elif defined(_LIBCPP_VERSION)
64 static_assert(std::__is_swappable_v
<Hash
>, "");
67 // Hashable requirements
68 static_assert(can_hash
<Hash
, Key
&>(), "");
69 static_assert(can_hash
<Hash
, Key
const&>(), "");
70 static_assert(can_hash
<Hash
, Key
&&>(), "");
71 static_assert(can_hash
<Hash
const, Key
&>(), "");
72 static_assert(can_hash
<Hash
const, Key
const&>(), "");
73 static_assert(can_hash
<Hash
const, Key
&&>(), "");
75 static_assert(can_hash
<Hash
, ConvertibleToSimple
<Key
>&>(), "");
76 static_assert(can_hash
<Hash
, ConvertibleToSimple
<Key
> const&>(), "");
77 static_assert(can_hash
<Hash
, ConvertibleToSimple
<Key
>&&>(), "");
79 static_assert(can_hash
<Hash
, ConvertibleTo
<Key
>&>(), "");
80 static_assert(can_hash
<Hash
, ConvertibleTo
<Key
> const&>(), "");
81 static_assert(can_hash
<Hash
, ConvertibleTo
<Key
>&&>(), "");
82 static_assert(can_hash
<Hash
, ConvertibleTo
<Key
> const&&>(), "");
85 assert(h(key
) == h(key
));
88 // Test that the specified Hash meets the requirements of a disabled hash.
89 template <class Key
, class Hash
= std::hash
<Key
>>
90 void test_hash_disabled() {
91 // Disabled hash requirements
92 static_assert(!std::is_default_constructible
<Hash
>::value
, "");
93 static_assert(!std::is_copy_constructible
<Hash
>::value
, "");
94 static_assert(!std::is_move_constructible
<Hash
>::value
, "");
95 static_assert(!std::is_copy_assignable
<Hash
>::value
, "");
96 static_assert(!std::is_move_assignable
<Hash
>::value
, "");
99 !std::is_function
<typename
std::remove_pointer
<typename
std::remove_reference
<Hash
>::type
>::type
>::value
, "");
101 // Hashable requirements
102 static_assert(!can_hash
<Hash
, Key
&>(), "");
103 static_assert(!can_hash
<Hash
, Key
const&>(), "");
104 static_assert(!can_hash
<Hash
, Key
&&>(), "");
105 static_assert(!can_hash
<Hash
const, Key
&>(), "");
106 static_assert(!can_hash
<Hash
const, Key
const&>(), "");
107 static_assert(!can_hash
<Hash
const, Key
&&>(), "");
109 static_assert(!can_hash
<Hash
, ConvertibleToSimple
<Key
>&>(), "");
110 static_assert(!can_hash
<Hash
, ConvertibleToSimple
<Key
> const&>(), "");
111 static_assert(!can_hash
<Hash
, ConvertibleToSimple
<Key
>&&>(), "");
113 static_assert(!can_hash
<Hash
, ConvertibleTo
<Key
>&>(), "");
114 static_assert(!can_hash
<Hash
, ConvertibleTo
<Key
> const&>(), "");
115 static_assert(!can_hash
<Hash
, ConvertibleTo
<Key
>&&>(), "");
116 static_assert(!can_hash
<Hash
, ConvertibleTo
<Key
> const&&>(), "");
120 enum EnumClass
: bool {};
123 // Each header that declares the std::hash template provides enabled
124 // specializations of std::hash for std::nullptr_t and all cv-unqualified
125 // arithmetic, enumeration, and pointer types.
126 #if TEST_STD_VER >= 17
127 using MaybeNullptr
= types::type_list
<std::nullptr_t
>;
129 using MaybeNullptr
= types::type_list
<>;
131 using LibraryHashTypes
= types::
132 concatenate_t
<types::arithmetic_types
, types::type_list
<Enum
, EnumClass
, void*, void const*, Class
*>, MaybeNullptr
>;
134 struct TestHashEnabled
{
136 void operator()() const {
137 test_hash_enabled
<T
>();
141 // Test that each of the library hash specializations for arithmetic types,
142 // enum types, and pointer types are available and enabled.
143 template <class Types
= LibraryHashTypes
>
144 void test_library_hash_specializations_available() {
145 types::for_each(Types(), TestHashEnabled());
148 #endif // SUPPORT_POISONED_HASH_HELPER_H