LLVM  3.7.0
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"
22 #include <cassert>
23 #include <new>
24 #include <utility>
25 
26 namespace llvm {
27 
28 template<typename T>
29 class Optional {
31  bool hasVal;
32 public:
33  typedef T value_type;
34 
35  Optional(NoneType) : hasVal(false) {}
36  explicit Optional() : hasVal(false) {}
37  Optional(const T &y) : hasVal(true) {
38  new (storage.buffer) T(y);
39  }
40  Optional(const Optional &O) : hasVal(O.hasVal) {
41  if (hasVal)
42  new (storage.buffer) T(*O);
43  }
44 
45  Optional(T &&y) : hasVal(true) {
46  new (storage.buffer) T(std::forward<T>(y));
47  }
48  Optional(Optional<T> &&O) : hasVal(O) {
49  if (O) {
50  new (storage.buffer) T(std::move(*O));
51  O.reset();
52  }
53  }
55  if (hasVal)
56  **this = std::move(y);
57  else {
58  new (storage.buffer) T(std::move(y));
59  hasVal = true;
60  }
61  return *this;
62  }
64  if (!O)
65  reset();
66  else {
67  *this = std::move(*O);
68  O.reset();
69  }
70  return *this;
71  }
72 
73  /// Create a new object by constructing it in place with the given arguments.
74  template<typename ...ArgTypes>
75  void emplace(ArgTypes &&...Args) {
76  reset();
77  hasVal = true;
78  new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
79  }
80 
81  static inline Optional create(const T* y) {
82  return y ? Optional(*y) : Optional();
83  }
84 
85  // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
86  // could be made more efficient by passing by value, possibly unifying them
87  // with the rvalue versions above - but this could place a different set of
88  // requirements (notably: the existence of a default ctor) when implemented
89  // in that way. Careful SFINAE to avoid such pitfalls would be required.
90  Optional &operator=(const T &y) {
91  if (hasVal)
92  **this = y;
93  else {
94  new (storage.buffer) T(y);
95  hasVal = true;
96  }
97  return *this;
98  }
99 
101  if (!O)
102  reset();
103  else
104  *this = *O;
105  return *this;
106  }
107 
108  void reset() {
109  if (hasVal) {
110  (**this).~T();
111  hasVal = false;
112  }
113  }
114 
116  reset();
117  }
118 
119  const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); }
120  T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); }
121  const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
122  T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
123 
124  explicit operator bool() const { return hasVal; }
125  bool hasValue() const { return hasVal; }
126  const T* operator->() const { return getPointer(); }
127  T* operator->() { return getPointer(); }
128  const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
129  T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
130 
131  template <typename U>
133  return hasValue() ? getValue() : std::forward<U>(value);
134  }
135 
136 #if LLVM_HAS_RVALUE_REFERENCE_THIS
137  T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
138  T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
139 
140  template <typename U>
141  T getValueOr(U &&value) && {
142  return hasValue() ? std::move(getValue()) : std::forward<U>(value);
143  }
144 #endif
145 };
146 
147 template <typename T> struct isPodLike;
148 template <typename T> struct isPodLike<Optional<T> > {
149  // An Optional<T> is pod-like if T is.
150  static const bool value = isPodLike<T>::value;
151 };
152 
153 /// \brief Poison comparison between two \c Optional objects. Clients needs to
154 /// explicitly compare the underlying values and account for empty \c Optional
155 /// objects.
156 ///
157 /// This routine will never be defined. It returns \c void to help diagnose
158 /// errors at compile time.
159 template<typename T, typename U>
160 void operator==(const Optional<T> &X, const Optional<U> &Y);
161 
162 /// \brief Poison comparison between two \c Optional objects. Clients needs to
163 /// explicitly compare the underlying values and account for empty \c Optional
164 /// objects.
165 ///
166 /// This routine will never be defined. It returns \c void to help diagnose
167 /// errors at compile time.
168 template<typename T, typename U>
169 void operator!=(const Optional<T> &X, const Optional<U> &Y);
170 
171 /// \brief Poison comparison between two \c Optional objects. Clients needs to
172 /// explicitly compare the underlying values and account for empty \c Optional
173 /// objects.
174 ///
175 /// This routine will never be defined. It returns \c void to help diagnose
176 /// errors at compile time.
177 template<typename T, typename U>
178 void operator<(const Optional<T> &X, const Optional<U> &Y);
179 
180 /// \brief Poison comparison between two \c Optional objects. Clients needs to
181 /// explicitly compare the underlying values and account for empty \c Optional
182 /// objects.
183 ///
184 /// This routine will never be defined. It returns \c void to help diagnose
185 /// errors at compile time.
186 template<typename T, typename U>
187 void operator<=(const Optional<T> &X, const Optional<U> &Y);
188 
189 /// \brief Poison comparison between two \c Optional objects. Clients needs to
190 /// explicitly compare the underlying values and account for empty \c Optional
191 /// objects.
192 ///
193 /// This routine will never be defined. It returns \c void to help diagnose
194 /// errors at compile time.
195 template<typename T, typename U>
196 void operator>=(const Optional<T> &X, const Optional<U> &Y);
197 
198 /// \brief Poison comparison between two \c Optional objects. Clients needs to
199 /// explicitly compare the underlying values and account for empty \c Optional
200 /// objects.
201 ///
202 /// This routine will never be defined. It returns \c void to help diagnose
203 /// errors at compile time.
204 template<typename T, typename U>
205 void operator>(const Optional<T> &X, const Optional<U> &Y);
206 
207 } // end llvm namespace
208 
209 #endif
Optional & operator=(Optional &&O)
Definition: Optional.h:63
Optional(const T &y)
Definition: Optional.h:37
const T & operator*() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:128
bool hasValue() const
Definition: Optional.h:125
NoneType
A simple null object to allow implicit construction of Optional<T> and similar types without having to ...
Definition: None.h:22
bool operator>(int64_t V1, const APSInt &V2)
Definition: APSInt.h:333
static const bool value
Definition: type_traits.h:46
LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION
Definition: Optional.h:132
#define LLVM_CONSTEXPR
Definition: Compiler.h:98
T & getValue() LLVM_LVALUE_FUNCTION
Definition: Optional.h:122
bool operator>=(int64_t V1, const APSInt &V2)
Definition: APSInt.h:331
#define LLVM_LVALUE_FUNCTION
Expands to '&' if ref-qualifiers for *this are supported.
Definition: Compiler.h:92
const T * operator->() const
Definition: Optional.h:126
#define false
Definition: ConvertUTF.c:65
Optional & operator=(const T &y)
Definition: Optional.h:90
#define T
const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:121
T * operator->()
Definition: Optional.h:127
#define true
Definition: ConvertUTF.c:66
static Optional create(const T *y)
Definition: Optional.h:81
const T * getPointer() const
Definition: Optional.h:119
Optional(NoneType)
Definition: Optional.h:35
T & operator*() LLVM_LVALUE_FUNCTION
Definition: Optional.h:129
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
isPodLike - This is a type trait that is used to determine whether a given type can be copied around ...
Definition: ArrayRef.h:365
Optional(Optional< T > &&O)
Definition: Optional.h:48
Optional(const Optional &O)
Definition: Optional.h:40
bool operator!=(uint64_t V1, const APInt &V2)
Definition: APInt.h:1736
Optional & operator=(T &&y)
Definition: Optional.h:54
void reset()
Definition: Optional.h:108
aarch64 promote const
Optional(T &&y)
Definition: Optional.h:45
T * getPointer()
Definition: Optional.h:120
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml","ocaml 3.10-compatible collector")
bool operator==(uint64_t V1, const APInt &V2)
Definition: APInt.h:1734
void emplace(ArgTypes &&...Args)
Create a new object by constructing it in place with the given arguments.
Definition: Optional.h:75
Optional & operator=(const Optional &O)
Definition: Optional.h:100