Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
5.9 KiB

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