]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/ADT/Optional.h
Merge compiler-rt trunk r321414 to contrib/compiler-rt.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / ADT / Optional.h
1 //===- Optional.h - Simple variant for passing optional values --*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file provides Optional, a template class modeled in the spirit of
11 //  OCaml's 'opt' variant.  The idea is to strongly type whether or not
12 //  a value can be optional.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_ADT_OPTIONAL_H
17 #define LLVM_ADT_OPTIONAL_H
18
19 #include "llvm/ADT/None.h"
20 #include "llvm/Support/AlignOf.h"
21 #include "llvm/Support/Compiler.h"
22 #include "llvm/Support/type_traits.h"
23 #include <algorithm>
24 #include <cassert>
25 #include <new>
26 #include <utility>
27
28 namespace llvm {
29
30 template <typename T> class Optional {
31   AlignedCharArrayUnion<T> storage;
32   bool hasVal = false;
33
34 public:
35   using value_type = T;
36
37   Optional(NoneType) {}
38   explicit Optional() {}
39
40   Optional(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
41
42   Optional(const Optional &O) : hasVal(O.hasVal) {
43     if (hasVal)
44       new (storage.buffer) T(*O);
45   }
46
47   Optional(T &&y) : hasVal(true) { new (storage.buffer) T(std::forward<T>(y)); }
48
49   Optional(Optional<T> &&O) : hasVal(O) {
50     if (O) {
51       new (storage.buffer) T(std::move(*O));
52       O.reset();
53     }
54   }
55
56   ~Optional() { reset(); }
57
58   Optional &operator=(T &&y) {
59     if (hasVal)
60       **this = std::move(y);
61     else {
62       new (storage.buffer) T(std::move(y));
63       hasVal = true;
64     }
65     return *this;
66   }
67
68   Optional &operator=(Optional &&O) {
69     if (!O)
70       reset();
71     else {
72       *this = std::move(*O);
73       O.reset();
74     }
75     return *this;
76   }
77
78   /// Create a new object by constructing it in place with the given arguments.
79   template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
80     reset();
81     hasVal = true;
82     new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
83   }
84
85   static inline Optional create(const T *y) {
86     return y ? Optional(*y) : Optional();
87   }
88
89   // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
90   // could be made more efficient by passing by value, possibly unifying them
91   // with the rvalue versions above - but this could place a different set of
92   // requirements (notably: the existence of a default ctor) when implemented
93   // in that way. Careful SFINAE to avoid such pitfalls would be required.
94   Optional &operator=(const T &y) {
95     if (hasVal)
96       **this = y;
97     else {
98       new (storage.buffer) T(y);
99       hasVal = true;
100     }
101     return *this;
102   }
103
104   Optional &operator=(const Optional &O) {
105     if (!O)
106       reset();
107     else
108       *this = *O;
109     return *this;
110   }
111
112   void reset() {
113     if (hasVal) {
114       (**this).~T();
115       hasVal = false;
116     }
117   }
118
119   const T *getPointer() const {
120     assert(hasVal);
121     return reinterpret_cast<const T *>(storage.buffer);
122   }
123   T *getPointer() {
124     assert(hasVal);
125     return reinterpret_cast<T *>(storage.buffer);
126   }
127   const T &getValue() const LLVM_LVALUE_FUNCTION {
128     assert(hasVal);
129     return *getPointer();
130   }
131   T &getValue() LLVM_LVALUE_FUNCTION {
132     assert(hasVal);
133     return *getPointer();
134   }
135
136   explicit operator bool() const { return hasVal; }
137   bool hasValue() const { return hasVal; }
138   const T *operator->() const { return getPointer(); }
139   T *operator->() { return getPointer(); }
140   const T &operator*() const LLVM_LVALUE_FUNCTION {
141     assert(hasVal);
142     return *getPointer();
143   }
144   T &operator*() LLVM_LVALUE_FUNCTION {
145     assert(hasVal);
146     return *getPointer();
147   }
148
149   template <typename U>
150   constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
151     return hasValue() ? getValue() : std::forward<U>(value);
152   }
153
154 #if LLVM_HAS_RVALUE_REFERENCE_THIS
155   T &&getValue() && {
156     assert(hasVal);
157     return std::move(*getPointer());
158   }
159   T &&operator*() && {
160     assert(hasVal);
161     return std::move(*getPointer());
162   }
163
164   template <typename U>
165   T getValueOr(U &&value) && {
166     return hasValue() ? std::move(getValue()) : std::forward<U>(value);
167   }
168 #endif
169 };
170
171 template <typename T> struct isPodLike<Optional<T>> {
172   // An Optional<T> is pod-like if T is.
173   static const bool value = isPodLike<T>::value;
174 };
175
176 template <typename T, typename U>
177 bool operator==(const Optional<T> &X, const Optional<U> &Y) {
178   if (X && Y)
179     return *X == *Y;
180   return X.hasValue() == Y.hasValue();
181 }
182
183 template <typename T, typename U>
184 bool operator!=(const Optional<T> &X, const Optional<U> &Y) {
185   return !(X == Y);
186 }
187
188 template <typename T, typename U>
189 bool operator<(const Optional<T> &X, const Optional<U> &Y) {
190   if (X && Y)
191     return *X < *Y;
192   return X.hasValue() < Y.hasValue();
193 }
194
195 template <typename T, typename U>
196 bool operator<=(const Optional<T> &X, const Optional<U> &Y) {
197   return !(Y < X);
198 }
199
200 template <typename T, typename U>
201 bool operator>(const Optional<T> &X, const Optional<U> &Y) {
202   return Y < X;
203 }
204
205 template <typename T, typename U>
206 bool operator>=(const Optional<T> &X, const Optional<U> &Y) {
207   return !(X < Y);
208 }
209
210 template<typename T>
211 bool operator==(const Optional<T> &X, NoneType) {
212   return !X;
213 }
214
215 template<typename T>
216 bool operator==(NoneType, const Optional<T> &X) {
217   return X == None;
218 }
219
220 template<typename T>
221 bool operator!=(const Optional<T> &X, NoneType) {
222   return !(X == None);
223 }
224
225 template<typename T>
226 bool operator!=(NoneType, const Optional<T> &X) {
227   return X != None;
228 }
229
230 template <typename T> bool operator<(const Optional<T> &X, NoneType) {
231   return false;
232 }
233
234 template <typename T> bool operator<(NoneType, const Optional<T> &X) {
235   return X.hasValue();
236 }
237
238 template <typename T> bool operator<=(const Optional<T> &X, NoneType) {
239   return !(None < X);
240 }
241
242 template <typename T> bool operator<=(NoneType, const Optional<T> &X) {
243   return !(X < None);
244 }
245
246 template <typename T> bool operator>(const Optional<T> &X, NoneType) {
247   return None < X;
248 }
249
250 template <typename T> bool operator>(NoneType, const Optional<T> &X) {
251   return X < None;
252 }
253
254 template <typename T> bool operator>=(const Optional<T> &X, NoneType) {
255   return None <= X;
256 }
257
258 template <typename T> bool operator>=(NoneType, const Optional<T> &X) {
259   return X <= None;
260 }
261
262 template <typename T> bool operator==(const Optional<T> &X, const T &Y) {
263   return X && *X == Y;
264 }
265
266 template <typename T> bool operator==(const T &X, const Optional<T> &Y) {
267   return Y && X == *Y;
268 }
269
270 template <typename T> bool operator!=(const Optional<T> &X, const T &Y) {
271   return !(X == Y);
272 }
273
274 template <typename T> bool operator!=(const T &X, const Optional<T> &Y) {
275   return !(X == Y);
276 }
277
278 template <typename T> bool operator<(const Optional<T> &X, const T &Y) {
279   return !X || *X < Y;
280 }
281
282 template <typename T> bool operator<(const T &X, const Optional<T> &Y) {
283   return Y && X < *Y;
284 }
285
286 template <typename T> bool operator<=(const Optional<T> &X, const T &Y) {
287   return !(Y < X);
288 }
289
290 template <typename T> bool operator<=(const T &X, const Optional<T> &Y) {
291   return !(Y < X);
292 }
293
294 template <typename T> bool operator>(const Optional<T> &X, const T &Y) {
295   return Y < X;
296 }
297
298 template <typename T> bool operator>(const T &X, const Optional<T> &Y) {
299   return Y < X;
300 }
301
302 template <typename T> bool operator>=(const Optional<T> &X, const T &Y) {
303   return !(X < Y);
304 }
305
306 template <typename T> bool operator>=(const T &X, const Optional<T> &Y) {
307   return !(X < Y);
308 }
309
310 } // end namespace llvm
311
312 #endif // LLVM_ADT_OPTIONAL_H