[ORC] Merge ostream operators for SymbolStringPtrs into SymbolStringPool.h. NFC.
[llvm-project.git] / libcxx / test / support / poisoned_hash_helper.h
blob93b579d2dfde3e9dac4207608c340def99f6014f
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
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
7 //
8 //===----------------------------------------------------------------------===//
10 #ifndef SUPPORT_POISONED_HASH_HELPER_H
11 #define SUPPORT_POISONED_HASH_HELPER_H
13 #include <functional>
14 #include <cassert>
15 #include <cstddef>
16 #include <type_traits>
17 #include <utility>
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) {
28 return false;
30 template <class Hash, class Key>
31 constexpr bool can_hash() {
32 return can_hash_impl<Hash, Key>(0);
35 template <class To>
36 struct ConvertibleToSimple {
37 operator To() const { return To{}; }
40 template <class To>
41 struct ConvertibleTo {
42 To to{};
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, "");
61 #if TEST_STD_VER > 14
62 static_assert(std::is_swappable<Hash>::value, "");
63 #elif defined(_LIBCPP_VERSION)
64 static_assert(std::__is_swappable_v<Hash>, "");
65 #endif
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&&>(), "");
84 const Hash h{};
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, "");
98 static_assert(
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&&>(), "");
119 enum Enum {};
120 enum EnumClass : bool {};
121 struct Class {};
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>;
128 #else
129 using MaybeNullptr = types::type_list<>;
130 #endif
131 using LibraryHashTypes = types::
132 concatenate_t<types::arithmetic_types, types::type_list<Enum, EnumClass, void*, void const*, Class*>, MaybeNullptr>;
134 struct TestHashEnabled {
135 template <class T>
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