Optional.h 13 KB

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