LLVM  6.0.0svn
Optional.h
Go to the documentation of this file.
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"
23 #include <algorithm>
24 #include <cassert>
25 #include <new>
26 #include <utility>
27 
28 namespace llvm {
29 
30 template <typename T> class Optional {
32  bool hasVal = false;
33 
34 public:
35  using value_type = T;
36 
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 
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 
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 
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  }
124  assert(hasVal);
125  return reinterpret_cast<T *>(storage.buffer);
126  }
128  assert(hasVal);
129  return *getPointer();
130  }
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(); }
141  assert(hasVal);
142  return *getPointer();
143  }
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
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Optional & operator=(Optional &&O)
Definition: Optional.h:68
Optional(const T &y)
Definition: Optional.h:40
const T & operator*() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:140
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
NoneType
A simple null object to allow implicit construction of Optional<T> and similar types without having t...
Definition: None.h:23
bool operator>(int64_t V1, const APSInt &V2)
Definition: APSInt.h:327
constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION
Definition: Optional.h:150
void emplace(ArgTypes &&... Args)
Create a new object by constructing it in place with the given arguments.
Definition: Optional.h:79
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
T & getValue() LLVM_LVALUE_FUNCTION
Definition: Optional.h:131
bool operator>=(int64_t V1, const APSInt &V2)
Definition: APSInt.h:325
#define LLVM_LVALUE_FUNCTION
Expands to &#39;&&#39; if ref-qualifiers for *this are supported.
Definition: Compiler.h:93
Optional & operator=(const T &y)
Definition: Optional.h:94
#define T
const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:127
T * operator->()
Definition: Optional.h:139
const T * operator->() const
Definition: Optional.h:138
static Optional create(const T *y)
Definition: Optional.h:85
Optional(NoneType)
Definition: Optional.h:37
T & operator*() LLVM_LVALUE_FUNCTION
Definition: Optional.h:144
const T * getPointer() const
Definition: Optional.h:119
char buffer[Size]
Definition: AlignOf.h:37
isPodLike - This is a type trait that is used to determine whether a given type can be copied around ...
Definition: ArrayRef.h:530
Optional(Optional< T > &&O)
Definition: Optional.h:49
Optional(const Optional &O)
Definition: Optional.h:42
bool operator!=(uint64_t V1, const APInt &V2)
Definition: APInt.h:1948
Basic Alias true
bool hasValue() const
Definition: Optional.h:137
Optional & operator=(T &&y)
Definition: Optional.h:58
void reset()
Definition: Optional.h:112
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
aarch64 promote const
Optional(T &&y)
Definition: Optional.h:47
T * getPointer()
Definition: Optional.h:123
bool operator==(uint64_t V1, const APInt &V2)
Definition: APInt.h:1946
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Optional & operator=(const Optional &O)
Definition: Optional.h:104