LLVM API Documentation
00001 //===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file provides Optional, a template class modeled in the spirit of 00011 // OCaml's 'opt' variant. The idea is to strongly type whether or not 00012 // a value can be optional. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #ifndef LLVM_ADT_OPTIONAL_H 00017 #define LLVM_ADT_OPTIONAL_H 00018 00019 #include "llvm/ADT/None.h" 00020 #include "llvm/Support/AlignOf.h" 00021 #include "llvm/Support/Compiler.h" 00022 #include <cassert> 00023 #include <utility> 00024 00025 namespace llvm { 00026 00027 template<typename T> 00028 class Optional { 00029 AlignedCharArrayUnion<T> storage; 00030 bool hasVal; 00031 public: 00032 Optional(NoneType) : hasVal(false) {} 00033 explicit Optional() : hasVal(false) {} 00034 Optional(const T &y) : hasVal(true) { 00035 new (storage.buffer) T(y); 00036 } 00037 Optional(const Optional &O) : hasVal(O.hasVal) { 00038 if (hasVal) 00039 new (storage.buffer) T(*O); 00040 } 00041 00042 Optional(T &&y) : hasVal(true) { 00043 new (storage.buffer) T(std::forward<T>(y)); 00044 } 00045 Optional(Optional<T> &&O) : hasVal(O) { 00046 if (O) { 00047 new (storage.buffer) T(std::move(*O)); 00048 O.reset(); 00049 } 00050 } 00051 Optional &operator=(T &&y) { 00052 if (hasVal) 00053 **this = std::move(y); 00054 else { 00055 new (storage.buffer) T(std::move(y)); 00056 hasVal = true; 00057 } 00058 return *this; 00059 } 00060 Optional &operator=(Optional &&O) { 00061 if (!O) 00062 reset(); 00063 else { 00064 *this = std::move(*O); 00065 O.reset(); 00066 } 00067 return *this; 00068 } 00069 00070 static inline Optional create(const T* y) { 00071 return y ? Optional(*y) : Optional(); 00072 } 00073 00074 // FIXME: these assignments (& the equivalent const T&/const Optional& ctors) 00075 // could be made more efficient by passing by value, possibly unifying them 00076 // with the rvalue versions above - but this could place a different set of 00077 // requirements (notably: the existence of a default ctor) when implemented 00078 // in that way. Careful SFINAE to avoid such pitfalls would be required. 00079 Optional &operator=(const T &y) { 00080 if (hasVal) 00081 **this = y; 00082 else { 00083 new (storage.buffer) T(y); 00084 hasVal = true; 00085 } 00086 return *this; 00087 } 00088 00089 Optional &operator=(const Optional &O) { 00090 if (!O) 00091 reset(); 00092 else 00093 *this = *O; 00094 return *this; 00095 } 00096 00097 void reset() { 00098 if (hasVal) { 00099 (**this).~T(); 00100 hasVal = false; 00101 } 00102 } 00103 00104 ~Optional() { 00105 reset(); 00106 } 00107 00108 const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); } 00109 T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); } 00110 const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 00111 T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 00112 00113 LLVM_EXPLICIT operator bool() const { return hasVal; } 00114 bool hasValue() const { return hasVal; } 00115 const T* operator->() const { return getPointer(); } 00116 T* operator->() { return getPointer(); } 00117 const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 00118 T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } 00119 00120 #if LLVM_HAS_RVALUE_REFERENCE_THIS 00121 T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } 00122 T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } 00123 #endif 00124 }; 00125 00126 template <typename T> struct isPodLike; 00127 template <typename T> struct isPodLike<Optional<T> > { 00128 // An Optional<T> is pod-like if T is. 00129 static const bool value = isPodLike<T>::value; 00130 }; 00131 00132 /// \brief Poison comparison between two \c Optional objects. Clients needs to 00133 /// explicitly compare the underlying values and account for empty \c Optional 00134 /// objects. 00135 /// 00136 /// This routine will never be defined. It returns \c void to help diagnose 00137 /// errors at compile time. 00138 template<typename T, typename U> 00139 void operator==(const Optional<T> &X, const Optional<U> &Y); 00140 00141 /// \brief Poison comparison between two \c Optional objects. Clients needs to 00142 /// explicitly compare the underlying values and account for empty \c Optional 00143 /// objects. 00144 /// 00145 /// This routine will never be defined. It returns \c void to help diagnose 00146 /// errors at compile time. 00147 template<typename T, typename U> 00148 void operator!=(const Optional<T> &X, const Optional<U> &Y); 00149 00150 /// \brief Poison comparison between two \c Optional objects. Clients needs to 00151 /// explicitly compare the underlying values and account for empty \c Optional 00152 /// objects. 00153 /// 00154 /// This routine will never be defined. It returns \c void to help diagnose 00155 /// errors at compile time. 00156 template<typename T, typename U> 00157 void operator<(const Optional<T> &X, const Optional<U> &Y); 00158 00159 /// \brief Poison comparison between two \c Optional objects. Clients needs to 00160 /// explicitly compare the underlying values and account for empty \c Optional 00161 /// objects. 00162 /// 00163 /// This routine will never be defined. It returns \c void to help diagnose 00164 /// errors at compile time. 00165 template<typename T, typename U> 00166 void operator<=(const Optional<T> &X, const Optional<U> &Y); 00167 00168 /// \brief Poison comparison between two \c Optional objects. Clients needs to 00169 /// explicitly compare the underlying values and account for empty \c Optional 00170 /// objects. 00171 /// 00172 /// This routine will never be defined. It returns \c void to help diagnose 00173 /// errors at compile time. 00174 template<typename T, typename U> 00175 void operator>=(const Optional<T> &X, const Optional<U> &Y); 00176 00177 /// \brief Poison comparison between two \c Optional objects. Clients needs to 00178 /// explicitly compare the underlying values and account for empty \c Optional 00179 /// objects. 00180 /// 00181 /// This routine will never be defined. It returns \c void to help diagnose 00182 /// errors at compile time. 00183 template<typename T, typename U> 00184 void operator>(const Optional<T> &X, const Optional<U> &Y); 00185 00186 } // end llvm namespace 00187 00188 #endif