KSOptional.h 6.8 KB

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