Optional.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- Optional.h - Simple variant for passing optional values --*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file provides Optional, a template class modeled in the spirit of
  15. // OCaml's 'opt' variant. The idea is to strongly type whether or not
  16. // a value can be optional.
  17. //
  18. //===----------------------------------------------------------------------===//
  19. #ifndef LLVM_ADT_OPTIONAL_H
  20. #define LLVM_ADT_OPTIONAL_H
  21. #include "llvm/ADT/Hashing.h"
  22. #include "llvm/ADT/None.h"
  23. #include "llvm/Support/Compiler.h"
  24. #include "llvm/Support/type_traits.h"
  25. #include <cassert>
  26. #include <memory>
  27. #include <new>
  28. #include <utility>
  29. namespace llvm {
  30. class raw_ostream;
  31. namespace optional_detail {
  32. struct in_place_t {};
  33. /// Storage for any type.
  34. //
  35. // The specialization condition intentionally uses
  36. // llvm::is_trivially_copy_constructible instead of
  37. // std::is_trivially_copy_constructible. GCC versions prior to 7.4 may
  38. // instantiate the copy constructor of `T` when
  39. // std::is_trivially_copy_constructible is instantiated. This causes
  40. // compilation to fail if we query the trivially copy constructible property of
  41. // a class which is not copy constructible.
  42. //
  43. // The current implementation of OptionalStorage insists that in order to use
  44. // the trivial specialization, the value_type must be trivially copy
  45. // constructible and trivially copy assignable due to =default implementations
  46. // of the copy/move constructor/assignment. It does not follow that this is
  47. // necessarily the case std::is_trivially_copyable is true (hence the expanded
  48. // specialization condition).
  49. //
  50. // The move constructible / assignable conditions emulate the remaining behavior
  51. // of std::is_trivially_copyable.
  52. template <typename T, bool = (llvm::is_trivially_copy_constructible<T>::value &&
  53. std::is_trivially_copy_assignable<T>::value &&
  54. (std::is_trivially_move_constructible<T>::value ||
  55. !std::is_move_constructible<T>::value) &&
  56. (std::is_trivially_move_assignable<T>::value ||
  57. !std::is_move_assignable<T>::value))>
  58. class OptionalStorage {
  59. union {
  60. char empty;
  61. T value;
  62. };
  63. bool hasVal;
  64. public:
  65. ~OptionalStorage() { reset(); }
  66. constexpr OptionalStorage() noexcept : empty(), hasVal(false) {}
  67. constexpr OptionalStorage(OptionalStorage const &other) : OptionalStorage() {
  68. if (other.hasValue()) {
  69. emplace(other.value);
  70. }
  71. }
  72. constexpr OptionalStorage(OptionalStorage &&other) : OptionalStorage() {
  73. if (other.hasValue()) {
  74. emplace(std::move(other.value));
  75. }
  76. }
  77. template <class... Args>
  78. constexpr explicit OptionalStorage(in_place_t, Args &&... args)
  79. : value(std::forward<Args>(args)...), hasVal(true) {}
  80. void reset() noexcept {
  81. if (hasVal) {
  82. value.~T();
  83. hasVal = false;
  84. }
  85. }
  86. constexpr bool hasValue() const noexcept { return hasVal; }
  87. T &getValue() LLVM_LVALUE_FUNCTION noexcept {
  88. assert(hasVal);
  89. return value;
  90. }
  91. constexpr T const &getValue() const LLVM_LVALUE_FUNCTION noexcept {
  92. assert(hasVal);
  93. return value;
  94. }
  95. #if LLVM_HAS_RVALUE_REFERENCE_THIS
  96. T &&getValue() && noexcept {
  97. assert(hasVal);
  98. return std::move(value);
  99. }
  100. #endif
  101. template <class... Args> void emplace(Args &&... args) {
  102. reset();
  103. ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...);
  104. hasVal = true;
  105. }
  106. OptionalStorage &operator=(T const &y) {
  107. if (hasValue()) {
  108. value = y;
  109. } else {
  110. ::new ((void *)std::addressof(value)) T(y);
  111. hasVal = true;
  112. }
  113. return *this;
  114. }
  115. OptionalStorage &operator=(T &&y) {
  116. if (hasValue()) {
  117. value = std::move(y);
  118. } else {
  119. ::new ((void *)std::addressof(value)) T(std::move(y));
  120. hasVal = true;
  121. }
  122. return *this;
  123. }
  124. OptionalStorage &operator=(OptionalStorage const &other) {
  125. if (other.hasValue()) {
  126. if (hasValue()) {
  127. value = other.value;
  128. } else {
  129. ::new ((void *)std::addressof(value)) T(other.value);
  130. hasVal = true;
  131. }
  132. } else {
  133. reset();
  134. }
  135. return *this;
  136. }
  137. OptionalStorage &operator=(OptionalStorage &&other) {
  138. if (other.hasValue()) {
  139. if (hasValue()) {
  140. value = std::move(other.value);
  141. } else {
  142. ::new ((void *)std::addressof(value)) T(std::move(other.value));
  143. hasVal = true;
  144. }
  145. } else {
  146. reset();
  147. }
  148. return *this;
  149. }
  150. };
  151. template <typename T> class OptionalStorage<T, true> {
  152. union {
  153. char empty;
  154. T value;
  155. };
  156. bool hasVal = false;
  157. public:
  158. ~OptionalStorage() = default;
  159. constexpr OptionalStorage() noexcept : empty{} {}
  160. constexpr OptionalStorage(OptionalStorage const &other) = default;
  161. constexpr OptionalStorage(OptionalStorage &&other) = default;
  162. OptionalStorage &operator=(OptionalStorage const &other) = default;
  163. OptionalStorage &operator=(OptionalStorage &&other) = default;
  164. template <class... Args>
  165. constexpr explicit OptionalStorage(in_place_t, Args &&... args)
  166. : value(std::forward<Args>(args)...), hasVal(true) {}
  167. void reset() noexcept {
  168. if (hasVal) {
  169. value.~T();
  170. hasVal = false;
  171. }
  172. }
  173. constexpr bool hasValue() const noexcept { return hasVal; }
  174. T &getValue() LLVM_LVALUE_FUNCTION noexcept {
  175. assert(hasVal);
  176. return value;
  177. }
  178. constexpr T const &getValue() const LLVM_LVALUE_FUNCTION noexcept {
  179. assert(hasVal);
  180. return value;
  181. }
  182. #if LLVM_HAS_RVALUE_REFERENCE_THIS
  183. T &&getValue() && noexcept {
  184. assert(hasVal);
  185. return std::move(value);
  186. }
  187. #endif
  188. template <class... Args> void emplace(Args &&... args) {
  189. reset();
  190. ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...);
  191. hasVal = true;
  192. }
  193. OptionalStorage &operator=(T const &y) {
  194. if (hasValue()) {
  195. value = y;
  196. } else {
  197. ::new ((void *)std::addressof(value)) T(y);
  198. hasVal = true;
  199. }
  200. return *this;
  201. }
  202. OptionalStorage &operator=(T &&y) {
  203. if (hasValue()) {
  204. value = std::move(y);
  205. } else {
  206. ::new ((void *)std::addressof(value)) T(std::move(y));
  207. hasVal = true;
  208. }
  209. return *this;
  210. }
  211. };
  212. } // namespace optional_detail
  213. template <typename T> class Optional {
  214. optional_detail::OptionalStorage<T> Storage;
  215. public:
  216. using value_type = T;
  217. constexpr Optional() {}
  218. constexpr Optional(NoneType) {}
  219. constexpr Optional(const T &y) : Storage(optional_detail::in_place_t{}, y) {}
  220. constexpr Optional(const Optional &O) = default;
  221. constexpr Optional(T &&y)
  222. : Storage(optional_detail::in_place_t{}, std::move(y)) {}
  223. constexpr Optional(Optional &&O) = default;
  224. Optional &operator=(T &&y) {
  225. Storage = std::move(y);
  226. return *this;
  227. }
  228. Optional &operator=(Optional &&O) = default;
  229. /// Create a new object by constructing it in place with the given arguments.
  230. template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
  231. Storage.emplace(std::forward<ArgTypes>(Args)...);
  232. }
  233. static constexpr Optional create(const T *y) {
  234. return y ? Optional(*y) : Optional();
  235. }
  236. Optional &operator=(const T &y) {
  237. Storage = y;
  238. return *this;
  239. }
  240. Optional &operator=(const Optional &O) = default;
  241. void reset() { Storage.reset(); }
  242. constexpr const T *getPointer() const { return &Storage.getValue(); }
  243. T *getPointer() { return &Storage.getValue(); }
  244. constexpr const T &getValue() const LLVM_LVALUE_FUNCTION {
  245. return Storage.getValue();
  246. }
  247. T &getValue() LLVM_LVALUE_FUNCTION { return Storage.getValue(); }
  248. constexpr explicit operator bool() const { return hasValue(); }
  249. constexpr bool hasValue() const { return Storage.hasValue(); }
  250. constexpr const T *operator->() const { return getPointer(); }
  251. T *operator->() { return getPointer(); }
  252. constexpr const T &operator*() const LLVM_LVALUE_FUNCTION {
  253. return getValue();
  254. }
  255. T &operator*() LLVM_LVALUE_FUNCTION { return getValue(); }
  256. template <typename U>
  257. constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
  258. return hasValue() ? getValue() : std::forward<U>(value);
  259. }
  260. /// Apply a function to the value if present; otherwise return None.
  261. template <class Function>
  262. auto map(const Function &F) const LLVM_LVALUE_FUNCTION
  263. -> Optional<decltype(F(getValue()))> {
  264. if (*this) return F(getValue());
  265. return None;
  266. }
  267. #if LLVM_HAS_RVALUE_REFERENCE_THIS
  268. T &&getValue() && { return std::move(Storage.getValue()); }
  269. T &&operator*() && { return std::move(Storage.getValue()); }
  270. template <typename U>
  271. T getValueOr(U &&value) && {
  272. return hasValue() ? std::move(getValue()) : std::forward<U>(value);
  273. }
  274. /// Apply a function to the value if present; otherwise return None.
  275. template <class Function>
  276. auto map(const Function &F) &&
  277. -> Optional<decltype(F(std::move(*this).getValue()))> {
  278. if (*this) return F(std::move(*this).getValue());
  279. return None;
  280. }
  281. #endif
  282. };
  283. template <class T> llvm::hash_code hash_value(const Optional<T> &O) {
  284. return O ? hash_combine(true, *O) : hash_value(false);
  285. }
  286. template <typename T, typename U>
  287. constexpr bool operator==(const Optional<T> &X, const Optional<U> &Y) {
  288. if (X && Y)
  289. return *X == *Y;
  290. return X.hasValue() == Y.hasValue();
  291. }
  292. template <typename T, typename U>
  293. constexpr bool operator!=(const Optional<T> &X, const Optional<U> &Y) {
  294. return !(X == Y);
  295. }
  296. template <typename T, typename U>
  297. constexpr bool operator<(const Optional<T> &X, const Optional<U> &Y) {
  298. if (X && Y)
  299. return *X < *Y;
  300. return X.hasValue() < Y.hasValue();
  301. }
  302. template <typename T, typename U>
  303. constexpr bool operator<=(const Optional<T> &X, const Optional<U> &Y) {
  304. return !(Y < X);
  305. }
  306. template <typename T, typename U>
  307. constexpr bool operator>(const Optional<T> &X, const Optional<U> &Y) {
  308. return Y < X;
  309. }
  310. template <typename T, typename U>
  311. constexpr bool operator>=(const Optional<T> &X, const Optional<U> &Y) {
  312. return !(X < Y);
  313. }
  314. template <typename T>
  315. constexpr bool operator==(const Optional<T> &X, NoneType) {
  316. return !X;
  317. }
  318. template <typename T>
  319. constexpr bool operator==(NoneType, const Optional<T> &X) {
  320. return X == None;
  321. }
  322. template <typename T>
  323. constexpr bool operator!=(const Optional<T> &X, NoneType) {
  324. return !(X == None);
  325. }
  326. template <typename T>
  327. constexpr bool operator!=(NoneType, const Optional<T> &X) {
  328. return X != None;
  329. }
  330. template <typename T> constexpr bool operator<(const Optional<T> &X, NoneType) {
  331. return false;
  332. }
  333. template <typename T> constexpr bool operator<(NoneType, const Optional<T> &X) {
  334. return X.hasValue();
  335. }
  336. template <typename T>
  337. constexpr bool operator<=(const Optional<T> &X, NoneType) {
  338. return !(None < X);
  339. }
  340. template <typename T>
  341. constexpr bool operator<=(NoneType, const Optional<T> &X) {
  342. return !(X < None);
  343. }
  344. template <typename T> constexpr bool operator>(const Optional<T> &X, NoneType) {
  345. return None < X;
  346. }
  347. template <typename T> constexpr bool operator>(NoneType, const Optional<T> &X) {
  348. return X < None;
  349. }
  350. template <typename T>
  351. constexpr bool operator>=(const Optional<T> &X, NoneType) {
  352. return None <= X;
  353. }
  354. template <typename T>
  355. constexpr bool operator>=(NoneType, const Optional<T> &X) {
  356. return X <= None;
  357. }
  358. template <typename T>
  359. constexpr bool operator==(const Optional<T> &X, const T &Y) {
  360. return X && *X == Y;
  361. }
  362. template <typename T>
  363. constexpr bool operator==(const T &X, const Optional<T> &Y) {
  364. return Y && X == *Y;
  365. }
  366. template <typename T>
  367. constexpr bool operator!=(const Optional<T> &X, const T &Y) {
  368. return !(X == Y);
  369. }
  370. template <typename T>
  371. constexpr bool operator!=(const T &X, const Optional<T> &Y) {
  372. return !(X == Y);
  373. }
  374. template <typename T>
  375. constexpr bool operator<(const Optional<T> &X, const T &Y) {
  376. return !X || *X < Y;
  377. }
  378. template <typename T>
  379. constexpr bool operator<(const T &X, const Optional<T> &Y) {
  380. return Y && X < *Y;
  381. }
  382. template <typename T>
  383. constexpr bool operator<=(const Optional<T> &X, const T &Y) {
  384. return !(Y < X);
  385. }
  386. template <typename T>
  387. constexpr bool operator<=(const T &X, const Optional<T> &Y) {
  388. return !(Y < X);
  389. }
  390. template <typename T>
  391. constexpr bool operator>(const Optional<T> &X, const T &Y) {
  392. return Y < X;
  393. }
  394. template <typename T>
  395. constexpr bool operator>(const T &X, const Optional<T> &Y) {
  396. return Y < X;
  397. }
  398. template <typename T>
  399. constexpr bool operator>=(const Optional<T> &X, const T &Y) {
  400. return !(X < Y);
  401. }
  402. template <typename T>
  403. constexpr bool operator>=(const T &X, const Optional<T> &Y) {
  404. return !(X < Y);
  405. }
  406. raw_ostream &operator<<(raw_ostream &OS, NoneType);
  407. template <typename T, typename = decltype(std::declval<raw_ostream &>()
  408. << std::declval<const T &>())>
  409. raw_ostream &operator<<(raw_ostream &OS, const Optional<T> &O) {
  410. if (O)
  411. OS << *O;
  412. else
  413. OS << None;
  414. return OS;
  415. }
  416. } // end namespace llvm
  417. #endif // LLVM_ADT_OPTIONAL_H
  418. #ifdef __GNUC__
  419. #pragma GCC diagnostic pop
  420. #endif