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
| 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 17#define LLVM_ADT_OPTIONAL
| 16#ifndef LLVM_ADT_OPTIONAL_H 17#define LLVM_ADT_OPTIONAL_H
|
18
| 18
|
| 19#include "llvm/ADT/None.h"
|
19#include "llvm/Support/Compiler.h"
| 20#include "llvm/Support/Compiler.h"
|
| 21#include "llvm/Support/AlignOf.h"
|
20#include <cassert> 21
| 22#include <cassert> 23
|
22#if LLVM_USE_RVALUE_REFERENCES
| 24#if LLVM_HAS_RVALUE_REFERENCES
|
23#include <utility> 24#endif 25 26namespace llvm { 27 28template<typename T> 29class Optional {
| 25#include <utility> 26#endif 27 28namespace llvm { 29 30template<typename T> 31class Optional {
|
30 T x; 31 unsigned hasVal : 1;
| 32 AlignedCharArrayUnion<T> storage; 33 bool hasVal;
|
32public:
| 34public:
|
33 explicit Optional() : x(), hasVal(false) {} 34 Optional(const T &y) : x(y), hasVal(true) {}
| 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 }
|
35
| 44
|
36#if LLVM_USE_RVALUE_REFERENCES 37 Optional(T &&y) : x(std::forward<T>(y)), hasVal(true) {}
| 45#if LLVM_HAS_RVALUE_REFERENCES 46 Optional(T &&y) : hasVal(true) { 47 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 Optional &operator=(T &&y) { 56 if (hasVal) 57 **this = std::move(y); 58 else { 59 new (storage.buffer) T(std::move(y)); 60 hasVal = true; 61 } 62 return *this; 63 } 64 Optional &operator=(Optional &&O) { 65 if (!O) 66 reset(); 67 else { 68 *this = std::move(*O); 69 O.reset(); 70 } 71 return *this; 72 }
|
38#endif 39 40 static inline Optional create(const T* y) { 41 return y ? Optional(*y) : Optional(); 42 } 43
| 73#endif 74 75 static inline Optional create(const T* y) { 76 return y ? Optional(*y) : Optional(); 77 } 78
|
| 79 // FIXME: these assignments (& the equivalent const T&/const Optional& ctors) 80 // could be made more efficient by passing by value, possibly unifying them 81 // with the rvalue versions above - but this could place a different set of 82 // requirements (notably: the existence of a default ctor) when implemented 83 // in that way. Careful SFINAE to avoid such pitfalls would be required.
|
44 Optional &operator=(const T &y) {
| 84 Optional &operator=(const T &y) {
|
45 x = y; 46 hasVal = true;
| 85 if (hasVal) 86 **this = y; 87 else { 88 new (storage.buffer) T(y); 89 hasVal = true; 90 }
|
47 return *this; 48 }
| 91 return *this; 92 }
|
49 50 const T* getPointer() const { assert(hasVal); return &x; } 51 const T& getValue() const { assert(hasVal); return x; }
| |
52
| 93
|
53 operator bool() const { return hasVal; }
| 94 Optional &operator=(const Optional &O) { 95 if (!O) 96 reset(); 97 else 98 *this = *O; 99 return *this; 100 } 101 102 void reset() { 103 if (hasVal) { 104 (**this).~T(); 105 hasVal = false; 106 } 107 } 108 109 ~Optional() { 110 reset(); 111 } 112 113 const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); } 114 T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); } 115 const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 116 T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 117 118 LLVM_EXPLICIT operator bool() const { return hasVal; }
|
54 bool hasValue() const { return hasVal; } 55 const T* operator->() const { return getPointer(); }
| 119 bool hasValue() const { return hasVal; } 120 const T* operator->() const { return getPointer(); }
|
56 const T& operator*() const { assert(hasVal); return x; }
| 121 T* operator->() { return getPointer(); } 122 const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 123 T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 124 125#if LLVM_HAS_RVALUE_REFERENCE_THIS 126 T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } 127 T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } 128#endif
|
57}; 58
| 129}; 130
|
59template<typename T> struct simplify_type; 60 61template <typename T> 62struct simplify_type<const Optional<T> > { 63 typedef const T* SimpleType; 64 static SimpleType getSimplifiedValue(const Optional<T> &Val) { 65 return Val.getPointer(); 66 }
| 131template <typename T> struct isPodLike; 132template <typename T> struct isPodLike<Optional<T> > { 133 // An Optional<T> is pod-like if T is. 134 static const bool value = isPodLike<T>::value;
|
67}; 68
| 135}; 136
|
69template <typename T> 70struct simplify_type<Optional<T> > 71 : public simplify_type<const Optional<T> > {}; 72
| |
73/// \brief Poison comparison between two \c Optional objects. Clients needs to 74/// explicitly compare the underlying values and account for empty \c Optional 75/// objects. 76///
| 137/// \brief Poison comparison between two \c Optional objects. Clients needs to 138/// explicitly compare the underlying values and account for empty \c Optional 139/// objects. 140///
|
77/// This routine will never be defined. It returns \c void to help diagnose
| 141/// This routine will never be defined. It returns \c void to help diagnose
|
78/// errors at compile time. 79template<typename T, typename U> 80void operator==(const Optional<T> &X, const Optional<U> &Y); 81 82/// \brief Poison comparison between two \c Optional objects. Clients needs to 83/// explicitly compare the underlying values and account for empty \c Optional 84/// objects. 85///
| 142/// errors at compile time. 143template<typename T, typename U> 144void operator==(const Optional<T> &X, const Optional<U> &Y); 145 146/// \brief Poison comparison between two \c Optional objects. Clients needs to 147/// explicitly compare the underlying values and account for empty \c Optional 148/// objects. 149///
|
86/// This routine will never be defined. It returns \c void to help diagnose
| 150/// This routine will never be defined. It returns \c void to help diagnose
|
87/// errors at compile time. 88template<typename T, typename U> 89void operator!=(const Optional<T> &X, const Optional<U> &Y); 90 91/// \brief Poison comparison between two \c Optional objects. Clients needs to 92/// explicitly compare the underlying values and account for empty \c Optional 93/// objects. 94///
| 151/// errors at compile time. 152template<typename T, typename U> 153void operator!=(const Optional<T> &X, const Optional<U> &Y); 154 155/// \brief Poison comparison between two \c Optional objects. Clients needs to 156/// explicitly compare the underlying values and account for empty \c Optional 157/// objects. 158///
|
95/// This routine will never be defined. It returns \c void to help diagnose
| 159/// This routine will never be defined. It returns \c void to help diagnose
|
96/// errors at compile time. 97template<typename T, typename U> 98void operator<(const Optional<T> &X, const Optional<U> &Y); 99 100/// \brief Poison comparison between two \c Optional objects. Clients needs to 101/// explicitly compare the underlying values and account for empty \c Optional 102/// objects. 103///
| 160/// errors at compile time. 161template<typename T, typename U> 162void operator<(const Optional<T> &X, const Optional<U> &Y); 163 164/// \brief Poison comparison between two \c Optional objects. Clients needs to 165/// explicitly compare the underlying values and account for empty \c Optional 166/// objects. 167///
|
104/// This routine will never be defined. It returns \c void to help diagnose
| 168/// This routine will never be defined. It returns \c void to help diagnose
|
105/// errors at compile time. 106template<typename T, typename U> 107void operator<=(const Optional<T> &X, const Optional<U> &Y); 108 109/// \brief Poison comparison between two \c Optional objects. Clients needs to 110/// explicitly compare the underlying values and account for empty \c Optional 111/// objects. 112///
| 169/// errors at compile time. 170template<typename T, typename U> 171void operator<=(const Optional<T> &X, const Optional<U> &Y); 172 173/// \brief Poison comparison between two \c Optional objects. Clients needs to 174/// explicitly compare the underlying values and account for empty \c Optional 175/// objects. 176///
|
113/// This routine will never be defined. It returns \c void to help diagnose
| 177/// This routine will never be defined. It returns \c void to help diagnose
|
114/// errors at compile time. 115template<typename T, typename U> 116void operator>=(const Optional<T> &X, const Optional<U> &Y); 117 118/// \brief Poison comparison between two \c Optional objects. Clients needs to 119/// explicitly compare the underlying values and account for empty \c Optional 120/// objects. 121///
| 178/// errors at compile time. 179template<typename T, typename U> 180void operator>=(const Optional<T> &X, const Optional<U> &Y); 181 182/// \brief Poison comparison between two \c Optional objects. Clients needs to 183/// explicitly compare the underlying values and account for empty \c Optional 184/// objects. 185///
|
122/// This routine will never be defined. It returns \c void to help diagnose
| 186/// This routine will never be defined. It returns \c void to help diagnose
|
123/// errors at compile time. 124template<typename T, typename U> 125void operator>(const Optional<T> &X, const Optional<U> &Y); 126 127} // end llvm namespace 128 129#endif
| 187/// errors at compile time. 188template<typename T, typename U> 189void operator>(const Optional<T> &X, const Optional<U> &Y); 190 191} // end llvm namespace 192 193#endif
|