]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/clang/include/clang/Basic/CustomizableOptional.h
Merge llvm-project main llvmorg-16-init-18548-gb0daacf58f41
[FreeBSD/FreeBSD.git] / contrib / llvm-project / clang / include / clang / Basic / CustomizableOptional.h
1 //===- CustomizableOptional.h - Optional with custom storage ----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef CLANG_BASIC_CUSTOMIZABLEOPTIONAL_H
10 #define CLANG_BASIC_CUSTOMIZABLEOPTIONAL_H
11
12 #include "llvm/ADT/Hashing.h"
13 #include "llvm/Support/Compiler.h"
14 #include "llvm/Support/type_traits.h"
15 #include <cassert>
16 #include <new>
17 #include <optional>
18 #include <utility>
19
20 namespace clang {
21
22 namespace optional_detail {
23 template <typename> class OptionalStorage;
24 } // namespace optional_detail
25
26 // Optional type which internal storage can be specialized by providing
27 // OptionalStorage. The interface follows std::optional.
28 template <typename T> class CustomizableOptional {
29   optional_detail::OptionalStorage<T> Storage;
30
31 public:
32   using value_type = T;
33
34   constexpr CustomizableOptional() = default;
35   constexpr CustomizableOptional(std::nullopt_t) {}
36
37   constexpr CustomizableOptional(const T &y) : Storage(std::in_place, y) {}
38   constexpr CustomizableOptional(const CustomizableOptional &O) = default;
39
40   constexpr CustomizableOptional(T &&y)
41       : Storage(std::in_place, std::move(y)) {}
42   constexpr CustomizableOptional(CustomizableOptional &&O) = default;
43
44   template <typename... ArgTypes>
45   constexpr CustomizableOptional(std::in_place_t, ArgTypes &&...Args)
46       : Storage(std::in_place, std::forward<ArgTypes>(Args)...) {}
47
48   // Allow conversion from std::optional<T>.
49   constexpr CustomizableOptional(const std::optional<T> &y)
50       : CustomizableOptional(y ? *y : CustomizableOptional()) {}
51   constexpr CustomizableOptional(std::optional<T> &&y)
52       : CustomizableOptional(y ? std::move(*y) : CustomizableOptional()) {}
53
54   CustomizableOptional &operator=(T &&y) {
55     Storage = std::move(y);
56     return *this;
57   }
58   CustomizableOptional &operator=(CustomizableOptional &&O) = default;
59
60   /// Create a new object by constructing it in place with the given arguments.
61   template <typename... ArgTypes> void emplace(ArgTypes &&...Args) {
62     Storage.emplace(std::forward<ArgTypes>(Args)...);
63   }
64
65   CustomizableOptional &operator=(const T &y) {
66     Storage = y;
67     return *this;
68   }
69   CustomizableOptional &operator=(const CustomizableOptional &O) = default;
70
71   void reset() { Storage.reset(); }
72
73   LLVM_DEPRECATED("Use &*X instead.", "&*X")
74   constexpr const T *getPointer() const { return &Storage.value(); }
75   LLVM_DEPRECATED("Use &*X instead.", "&*X")
76   T *getPointer() { return &Storage.value(); }
77   LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X")
78   constexpr const T &value() const & { return Storage.value(); }
79   LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X")
80   T &value() & { return Storage.value(); }
81
82   constexpr explicit operator bool() const { return has_value(); }
83   constexpr bool has_value() const { return Storage.has_value(); }
84   constexpr const T *operator->() const { return &Storage.value(); }
85   T *operator->() { return &Storage.value(); }
86   constexpr const T &operator*() const & { return Storage.value(); }
87   T &operator*() & { return Storage.value(); }
88
89   template <typename U> constexpr T value_or(U &&alt) const & {
90     return has_value() ? operator*() : std::forward<U>(alt);
91   }
92
93   LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X")
94   T &&value() && { return std::move(Storage.value()); }
95   T &&operator*() && { return std::move(Storage.value()); }
96
97   template <typename U> T value_or(U &&alt) && {
98     return has_value() ? std::move(operator*()) : std::forward<U>(alt);
99   }
100
101   // Allow conversion to std::optional<T>.
102   explicit operator std::optional<T> &() const & {
103     return *this ? **this : std::optional<T>();
104   }
105   explicit operator std::optional<T> &&() const && {
106     return *this ? std::move(**this) : std::optional<T>();
107   }
108 };
109
110 template <typename T>
111 CustomizableOptional(const T &) -> CustomizableOptional<T>;
112
113 template <class T>
114 llvm::hash_code hash_value(const CustomizableOptional<T> &O) {
115   return O ? llvm::hash_combine(true, *O) : llvm::hash_value(false);
116 }
117
118 template <typename T, typename U>
119 constexpr bool operator==(const CustomizableOptional<T> &X,
120                           const CustomizableOptional<U> &Y) {
121   if (X && Y)
122     return *X == *Y;
123   return X.has_value() == Y.has_value();
124 }
125
126 template <typename T, typename U>
127 constexpr bool operator!=(const CustomizableOptional<T> &X,
128                           const CustomizableOptional<U> &Y) {
129   return !(X == Y);
130 }
131
132 template <typename T, typename U>
133 constexpr bool operator<(const CustomizableOptional<T> &X,
134                          const CustomizableOptional<U> &Y) {
135   if (X && Y)
136     return *X < *Y;
137   return X.has_value() < Y.has_value();
138 }
139
140 template <typename T, typename U>
141 constexpr bool operator<=(const CustomizableOptional<T> &X,
142                           const CustomizableOptional<U> &Y) {
143   return !(Y < X);
144 }
145
146 template <typename T, typename U>
147 constexpr bool operator>(const CustomizableOptional<T> &X,
148                          const CustomizableOptional<U> &Y) {
149   return Y < X;
150 }
151
152 template <typename T, typename U>
153 constexpr bool operator>=(const CustomizableOptional<T> &X,
154                           const CustomizableOptional<U> &Y) {
155   return !(X < Y);
156 }
157
158 template <typename T>
159 constexpr bool operator==(const CustomizableOptional<T> &X, std::nullopt_t) {
160   return !X;
161 }
162
163 template <typename T>
164 constexpr bool operator==(std::nullopt_t, const CustomizableOptional<T> &X) {
165   return X == std::nullopt;
166 }
167
168 template <typename T>
169 constexpr bool operator!=(const CustomizableOptional<T> &X, std::nullopt_t) {
170   return !(X == std::nullopt);
171 }
172
173 template <typename T>
174 constexpr bool operator!=(std::nullopt_t, const CustomizableOptional<T> &X) {
175   return X != std::nullopt;
176 }
177
178 template <typename T>
179 constexpr bool operator<(const CustomizableOptional<T> &, std::nullopt_t) {
180   return false;
181 }
182
183 template <typename T>
184 constexpr bool operator<(std::nullopt_t, const CustomizableOptional<T> &X) {
185   return X.has_value();
186 }
187
188 template <typename T>
189 constexpr bool operator<=(const CustomizableOptional<T> &X, std::nullopt_t) {
190   return !(std::nullopt < X);
191 }
192
193 template <typename T>
194 constexpr bool operator<=(std::nullopt_t, const CustomizableOptional<T> &X) {
195   return !(X < std::nullopt);
196 }
197
198 template <typename T>
199 constexpr bool operator>(const CustomizableOptional<T> &X, std::nullopt_t) {
200   return std::nullopt < X;
201 }
202
203 template <typename T>
204 constexpr bool operator>(std::nullopt_t, const CustomizableOptional<T> &X) {
205   return X < std::nullopt;
206 }
207
208 template <typename T>
209 constexpr bool operator>=(const CustomizableOptional<T> &X, std::nullopt_t) {
210   return std::nullopt <= X;
211 }
212
213 template <typename T>
214 constexpr bool operator>=(std::nullopt_t, const CustomizableOptional<T> &X) {
215   return X <= std::nullopt;
216 }
217
218 template <typename T>
219 constexpr bool operator==(const CustomizableOptional<T> &X, const T &Y) {
220   return X && *X == Y;
221 }
222
223 template <typename T>
224 constexpr bool operator==(const T &X, const CustomizableOptional<T> &Y) {
225   return Y && X == *Y;
226 }
227
228 template <typename T>
229 constexpr bool operator!=(const CustomizableOptional<T> &X, const T &Y) {
230   return !(X == Y);
231 }
232
233 template <typename T>
234 constexpr bool operator!=(const T &X, const CustomizableOptional<T> &Y) {
235   return !(X == Y);
236 }
237
238 template <typename T>
239 constexpr bool operator<(const CustomizableOptional<T> &X, const T &Y) {
240   return !X || *X < Y;
241 }
242
243 template <typename T>
244 constexpr bool operator<(const T &X, const CustomizableOptional<T> &Y) {
245   return Y && X < *Y;
246 }
247
248 template <typename T>
249 constexpr bool operator<=(const CustomizableOptional<T> &X, const T &Y) {
250   return !(Y < X);
251 }
252
253 template <typename T>
254 constexpr bool operator<=(const T &X, const CustomizableOptional<T> &Y) {
255   return !(Y < X);
256 }
257
258 template <typename T>
259 constexpr bool operator>(const CustomizableOptional<T> &X, const T &Y) {
260   return Y < X;
261 }
262
263 template <typename T>
264 constexpr bool operator>(const T &X, const CustomizableOptional<T> &Y) {
265   return Y < X;
266 }
267
268 template <typename T>
269 constexpr bool operator>=(const CustomizableOptional<T> &X, const T &Y) {
270   return !(X < Y);
271 }
272
273 template <typename T>
274 constexpr bool operator>=(const T &X, const CustomizableOptional<T> &Y) {
275   return !(X < Y);
276 }
277
278 } // namespace clang
279
280 #endif // CLANG_BASIC_CUSTOMIZABLEOPTIONAL_H