16 #ifndef WPIUTIL_WPI_OPTIONAL_H
17 #define WPIUTIL_WPI_OPTIONAL_H
20 #include "wpi/AlignOf.h"
21 #include "wpi/Compiler.h"
22 #include "wpi/type_traits.h"
30 namespace optional_detail {
38 OptionalStorage(
const T &y) : hasVal(
true) {
new (storage.buffer) T(y); }
41 new (storage.buffer) T(*O.getPointer());
44 new (storage.buffer) T(std::forward<T>(y));
48 new (storage.buffer) T(std::move(*O.getPointer()));
54 *getPointer() = std::move(y);
56 new (storage.buffer) T(std::move(y));
65 *
this = std::move(*O.getPointer());
79 new (storage.buffer) T(y);
88 *
this = *O.getPointer();
103 return reinterpret_cast<T *
>(storage.buffer);
105 const T *getPointer()
const {
107 return reinterpret_cast<const T *
>(storage.buffer);
111 #if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this.
119 OptionalStorage(
const T &y) : hasVal(true) {
new (storage.buffer) T(y); }
120 OptionalStorage &operator=(
const T &y) {
121 *
reinterpret_cast<T *
>(storage.buffer) = y;
126 void reset() { hasVal =
false; }
135 using value_type = T;
140 Optional(
const T &y) : Storage(y) {}
143 Optional(T &&y) : Storage(std::forward<T>(y)) {}
147 Storage = std::move(y);
153 template <
typename... ArgTypes>
void emplace(ArgTypes &&... Args) {
155 Storage.hasVal =
true;
156 new (getPointer()) T(std::forward<ArgTypes>(Args)...);
159 static inline Optional create(
const T *y) {
160 return y ?
Optional(*y) : Optional();
163 Optional &operator=(
const T &y) {
167 Optional &operator=(
const Optional &O) =
default;
169 void reset() { Storage.reset(); }
171 const T *getPointer()
const {
172 assert(Storage.hasVal);
173 return reinterpret_cast<const T *
>(Storage.storage.buffer);
176 assert(Storage.hasVal);
177 return reinterpret_cast<T *
>(Storage.storage.buffer);
179 const T &getValue() const LLVM_LVALUE_FUNCTION {
return *getPointer(); }
180 T &getValue() LLVM_LVALUE_FUNCTION {
return *getPointer(); }
182 explicit operator bool()
const {
return Storage.hasVal; }
183 bool hasValue()
const {
return Storage.hasVal; }
184 const T *operator->()
const {
return getPointer(); }
185 T *operator->() {
return getPointer(); }
186 const T &operator*() const LLVM_LVALUE_FUNCTION {
return *getPointer(); }
187 T &operator*() LLVM_LVALUE_FUNCTION {
return *getPointer(); }
189 template <
typename U>
190 constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
191 return hasValue() ? getValue() :
std::forward<U>(value);
194 #if LLVM_HAS_RVALUE_REFERENCE_THIS
195 T &&getValue() && {
return std::move(*getPointer()); }
196 T &&operator*() && {
return std::move(*getPointer()); }
198 template <
typename U>
199 T getValueOr(U &&value) && {
200 return hasValue() ? std::move(getValue()) :
std::forward<U>(value);
210 template <
typename T,
typename U>
214 return X.hasValue() == Y.hasValue();
217 template <
typename T,
typename U>
218 bool operator!=(
const Optional<T> &X,
const Optional<U> &Y) {
222 template <
typename T,
typename U>
223 bool operator<(const Optional<T> &X,
const Optional<U> &Y) {
226 return X.hasValue() < Y.hasValue();
229 template <
typename T,
typename U>
230 bool operator<=(const Optional<T> &X,
const Optional<U> &Y) {
234 template <
typename T,
typename U>
235 bool operator>(
const Optional<T> &X,
const Optional<U> &Y) {
239 template <
typename T,
typename U>
240 bool operator>=(
const Optional<T> &X,
const Optional<U> &Y) {
245 bool operator==(
const Optional<T> &X,
NoneType) {
250 bool operator==(
NoneType,
const Optional<T> &X) {
255 bool operator!=(
const Optional<T> &X,
NoneType) {
260 bool operator!=(
NoneType,
const Optional<T> &X) {
264 template <
typename T>
bool operator<(const Optional<T> &X,
NoneType) {
268 template <
typename T>
bool operator<(NoneType, const Optional<T> &X) {
272 template <
typename T>
bool operator<=(const Optional<T> &X,
NoneType) {
276 template <
typename T>
bool operator<=(NoneType, const Optional<T> &X) {
280 template <
typename T>
bool operator>(
const Optional<T> &X,
NoneType) {
284 template <
typename T>
bool operator>(
NoneType,
const Optional<T> &X) {
288 template <
typename T>
bool operator>=(
const Optional<T> &X,
NoneType) {
292 template <
typename T>
bool operator>=(
NoneType,
const Optional<T> &X) {
296 template <
typename T>
bool operator==(
const Optional<T> &X,
const T &Y) {
300 template <
typename T>
bool operator==(
const T &X,
const Optional<T> &Y) {
304 template <
typename T>
bool operator!=(
const Optional<T> &X,
const T &Y) {
308 template <
typename T>
bool operator!=(
const T &X,
const Optional<T> &Y) {
312 template <
typename T>
bool operator<(const Optional<T> &X,
const T &Y) {
316 template <
typename T>
bool operator<(const T &X, const Optional<T> &Y) {
320 template <
typename T>
bool operator<=(const Optional<T> &X,
const T &Y) {
324 template <
typename T>
bool operator<=(const T &X, const Optional<T> &Y) {
328 template <
typename T>
bool operator>(
const Optional<T> &X,
const T &Y) {
332 template <
typename T>
bool operator>(
const T &X,
const Optional<T> &Y) {
336 template <
typename T>
bool operator>=(
const Optional<T> &X,
const T &Y) {
340 template <
typename T>
bool operator>=(
const T &X,
const Optional<T> &Y) {
Definition: SmallVector.h:946
namespace to hold default to_json function
Definition: SmallString.h:21
isPodLike - This is a type trait that is used to determine whether a given type can be copied around ...
Definition: ArrayRef.h:530
Storage for any type.
Definition: Optional.h:32
void emplace(ArgTypes &&...Args)
Create a new object by constructing it in place with the given arguments.
Definition: Optional.h:153
NoneType
A simple null object to allow implicit construction of Optional and similar types without having t...
Definition: None.h:23
Definition: Optional.h:131