[flang][runtime] Make defined formatted I/O process format elementally (#74150)
[llvm-project.git] / libcxx / test / support / poisoned_hash_helper.h
blob000b08cd37bebede208ad661101b6ecf51dc4d04
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 <cassert>
14 #include <cstddef>
15 #include <type_traits>
16 #include <utility>
18 #include "test_macros.h"
19 #include "test_workarounds.h"
21 #if TEST_STD_VER < 11
22 #error this header may only be used in C++11 or newer
23 #endif
25 template <class ...Args> struct TypeList;
27 // Test that the specified Hash meets the requirements of an enabled hash
28 template <class Hash, class Key, class InputKey = Key>
29 TEST_CONSTEXPR_CXX20 void test_hash_enabled(InputKey const& key = InputKey{});
31 template <class T, class InputKey = T>
32 TEST_CONSTEXPR_CXX20 void test_hash_enabled_for_type(InputKey const& key = InputKey{}) {
33 return test_hash_enabled<std::hash<T>, T, InputKey>(key);
36 // Test that the specified Hash meets the requirements of a disabled hash.
37 template <class Hash, class Key>
38 void test_hash_disabled();
40 template <class T>
41 void test_hash_disabled_for_type() {
42 return test_hash_disabled<std::hash<T>, T>();
45 namespace PoisonedHashDetail {
46 enum Enum {};
47 enum EnumClass : bool {};
48 struct Class {};
51 // Each header that declares the template hash provides enabled
52 // specializations of hash for nullptr t and all cv-unqualified
53 // arithmetic, enumeration, and pointer types.
54 using LibraryHashTypes = TypeList<
55 #if TEST_STD_VER > 14
56 decltype(nullptr),
57 #endif
58 bool,
59 char,
60 signed char,
61 unsigned char,
62 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
63 wchar_t,
64 #endif
65 char16_t,
66 char32_t,
67 short,
68 unsigned short,
69 int,
70 unsigned int,
71 long,
72 unsigned long,
73 long long,
74 unsigned long long,
75 #ifndef TEST_HAS_NO_INT128
76 __int128_t,
77 __uint128_t,
78 #endif
79 float,
80 double,
81 long double,
82 PoisonedHashDetail::Enum,
83 PoisonedHashDetail::EnumClass,
84 void*,
85 void const*,
86 PoisonedHashDetail::Class*
90 // Test that each of the library hash specializations for arithmetic types,
91 // enum types, and pointer types are available and enabled.
92 template <class Types = LibraryHashTypes>
93 void test_library_hash_specializations_available(Types = Types{});
96 namespace PoisonedHashDetail {
98 template <class T, class = typename T::foo_bar_baz>
99 constexpr bool instantiate(int) { return true; }
100 template <class> constexpr bool instantiate(long) { return true; }
101 template <class T> constexpr bool instantiate() { return instantiate<T>(0); }
103 template <class To>
104 struct ConvertibleToSimple {
105 operator To() const {
106 return To{};
110 template <class To>
111 struct ConvertibleTo {
112 To to{};
113 operator To&() & { return to; }
114 operator To const&() const & { return to; }
115 operator To&&() && { return std::move(to); }
116 operator To const&&() const && { return std::move(to); }
119 template <class Hasher, class Key, class Res = decltype(std::declval<Hasher&>()(std::declval<Key>()))>
120 constexpr bool can_hash(int) {
121 return std::is_same<Res, std::size_t>::value;
123 template <class, class>
124 constexpr bool can_hash(long) {
125 return false;
127 template <class Hasher, class Key>
128 constexpr bool can_hash() {
129 return can_hash<Hasher, Key>(0);
131 } // namespace PoisonedHashDetail
133 template <class Hash, class Key, class InputKey>
134 TEST_CONSTEXPR_CXX20 void test_hash_enabled(InputKey const& key) {
135 using namespace PoisonedHashDetail;
137 static_assert(std::is_destructible<Hash>::value, "");
138 // Enabled hash requirements
139 static_assert(std::is_default_constructible<Hash>::value, "");
140 static_assert(std::is_copy_constructible<Hash>::value, "");
141 static_assert(std::is_move_constructible<Hash>::value, "");
142 static_assert(std::is_copy_assignable<Hash>::value, "");
143 static_assert(std::is_move_assignable<Hash>::value, "");
145 #if TEST_STD_VER > 14
146 static_assert(std::is_swappable<Hash>::value, "");
147 #elif defined(_LIBCPP_VERSION)
148 static_assert(std::__is_swappable<Hash>::value, "");
149 #endif
151 // Hashable requirements
152 static_assert(can_hash<Hash, Key&>(), "");
153 static_assert(can_hash<Hash, Key const&>(), "");
154 static_assert(can_hash<Hash, Key&&>(), "");
155 static_assert(can_hash<Hash const, Key&>(), "");
156 static_assert(can_hash<Hash const, Key const&>(), "");
157 static_assert(can_hash<Hash const, Key&&>(), "");
159 static_assert(can_hash<Hash, ConvertibleToSimple<Key>&>(), "");
160 static_assert(can_hash<Hash, ConvertibleToSimple<Key> const&>(), "");
161 static_assert(can_hash<Hash, ConvertibleToSimple<Key>&&>(), "");
163 static_assert(can_hash<Hash, ConvertibleTo<Key>&>(), "");
164 static_assert(can_hash<Hash, ConvertibleTo<Key> const&>(), "");
165 static_assert(can_hash<Hash, ConvertibleTo<Key>&&>(), "");
166 static_assert(can_hash<Hash, ConvertibleTo<Key> const&&>(), "");
168 const Hash h{};
169 assert(h(key) == h(key));
173 template <class Hash, class Key>
174 void test_hash_disabled() {
175 using namespace PoisonedHashDetail;
177 // Disabled hash requirements
178 static_assert(!std::is_default_constructible<Hash>::value, "");
179 static_assert(!std::is_copy_constructible<Hash>::value, "");
180 static_assert(!std::is_move_constructible<Hash>::value, "");
181 static_assert(!std::is_copy_assignable<Hash>::value, "");
182 static_assert(!std::is_move_assignable<Hash>::value, "");
184 static_assert(!std::is_function<
185 typename std::remove_pointer<
186 typename std::remove_reference<Hash>::type
187 >::type
188 >::value, "");
190 // Hashable requirements
191 static_assert(!can_hash<Hash, Key&>(), "");
192 static_assert(!can_hash<Hash, Key const&>(), "");
193 static_assert(!can_hash<Hash, Key&&>(), "");
194 static_assert(!can_hash<Hash const, Key&>(), "");
195 static_assert(!can_hash<Hash const, Key const&>(), "");
196 static_assert(!can_hash<Hash const, Key&&>(), "");
198 static_assert(!can_hash<Hash, ConvertibleToSimple<Key>&>(), "");
199 static_assert(!can_hash<Hash, ConvertibleToSimple<Key> const&>(), "");
200 static_assert(!can_hash<Hash, ConvertibleToSimple<Key>&&>(), "");
202 static_assert(!can_hash<Hash, ConvertibleTo<Key>&>(), "");
203 static_assert(!can_hash<Hash, ConvertibleTo<Key> const&>(), "");
204 static_assert(!can_hash<Hash, ConvertibleTo<Key>&&>(), "");
205 static_assert(!can_hash<Hash, ConvertibleTo<Key> const&&>(), "");
209 template <class First, class ...Rest>
210 struct TypeList<First, Rest...> {
211 template <template <class> class Trait, bool Expect = true>
212 static constexpr bool assertTrait() {
213 static_assert(Trait<First>::value == Expect, "");
214 return TypeList<Rest...>::template assertTrait<Trait, Expect>();
217 template <class Trait>
218 static void applyTrait() {
219 Trait::template apply<First>();
220 TypeList<Rest...>::template applyTrait<Trait>();
224 template <>
225 struct TypeList<> {
226 template <template <class> class Trait, bool Expect = true>
227 static constexpr bool assertTrait() {
228 return true;
230 template <class Trait>
231 static void applyTrait() {}
235 struct TestLibraryTrait {
236 template <class Type>
237 static void apply() { test_hash_enabled<std::hash<Type>, Type>(); }
240 template <class Types>
241 void test_library_hash_specializations_available(Types) {
242 Types::template applyTrait<TestLibraryTrait >();
245 #endif // SUPPORT_POISONED_HASH_HELPER_H