optional 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. // -*-c++-*-
  2. // vim: set ft=cpp:
  3. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  4. file Copyright.txt or https://cmake.org/licensing for details. */
  5. #pragma once
  6. #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
  7. # define CMake_HAVE_CXX_OPTIONAL
  8. #endif
  9. #if defined(CMake_HAVE_CXX_OPTIONAL)
  10. # include <optional> // IWYU pragma: export
  11. #else
  12. # include <memory>
  13. # include <cm/utility>
  14. #endif
  15. namespace cm {
  16. #if defined(CMake_HAVE_CXX_OPTIONAL)
  17. using std::nullopt_t;
  18. using std::nullopt;
  19. using std::optional;
  20. using std::bad_optional_access;
  21. using std::make_optional;
  22. #else
  23. class bad_optional_access : public std::exception
  24. {
  25. using std::exception::exception;
  26. };
  27. struct nullopt_t
  28. {
  29. explicit constexpr nullopt_t(int) {}
  30. };
  31. constexpr nullopt_t nullopt{ 0 };
  32. template <typename T>
  33. class optional
  34. {
  35. public:
  36. using value_type = T;
  37. optional() noexcept = default;
  38. optional(nullopt_t) noexcept;
  39. optional(const optional& other);
  40. optional(optional&& other) noexcept;
  41. template <typename... Args>
  42. explicit optional(cm::in_place_t, Args&&... args);
  43. template <
  44. typename U = T,
  45. typename = typename std::enable_if<
  46. std::is_constructible<T, U&&>::value &&
  47. !std::is_same<typename std::decay<U>::type, cm::in_place_t>::value &&
  48. !std::is_same<typename std::decay<U>::type,
  49. cm::optional<T>>::value>::type>
  50. optional(U&& v);
  51. ~optional();
  52. optional& operator=(nullopt_t) noexcept;
  53. optional& operator=(const optional& other);
  54. optional& operator=(optional&& other) noexcept;
  55. template <
  56. typename U = T,
  57. typename = typename std::enable_if<
  58. !std::is_same<typename std::decay<U>::type, cm::optional<T>>::value &&
  59. std::is_constructible<T, U>::value && std::is_assignable<T&, U>::value &&
  60. (!std::is_scalar<T>::value ||
  61. !std::is_same<typename std::decay<U>::type, T>::value)>::type>
  62. optional& operator=(U&& v);
  63. const T* operator->() const;
  64. T* operator->();
  65. const T& operator*() const&;
  66. T& operator*() &;
  67. const T&& operator*() const&&;
  68. T&& operator*() &&;
  69. explicit operator bool() const noexcept;
  70. bool has_value() const noexcept;
  71. T& value() &;
  72. const T& value() const&;
  73. T&& value() &&;
  74. const T&& value() const&&;
  75. template <typename U>
  76. T value_or(U&& default_value) const&;
  77. template <typename U>
  78. T value_or(U&& default_value) &&;
  79. void swap(optional& other) noexcept;
  80. void reset() noexcept;
  81. template <typename... Args>
  82. T& emplace(Args&&... args);
  83. private:
  84. bool _has_value = false;
  85. std::allocator<T> _allocator;
  86. union _mem_union
  87. {
  88. T value;
  89. // Explicit constructor and destructor is required to make this work
  90. _mem_union() noexcept {}
  91. ~_mem_union() noexcept {}
  92. } _mem;
  93. };
  94. template <typename T>
  95. optional<typename std::decay<T>::type> make_optional(T&& value)
  96. {
  97. return optional<typename std::decay<T>::type>(std::forward<T>(value));
  98. }
  99. template <typename T, class... Args>
  100. optional<T> make_optional(Args&&... args)
  101. {
  102. return optional<T>(in_place, std::forward<Args>(args)...);
  103. }
  104. template <typename T>
  105. optional<T>::optional(nullopt_t) noexcept
  106. {
  107. }
  108. template <typename T>
  109. optional<T>::optional(const optional& other)
  110. {
  111. *this = other;
  112. }
  113. template <typename T>
  114. optional<T>::optional(optional&& other) noexcept
  115. {
  116. *this = std::move(other);
  117. }
  118. template <typename T>
  119. template <typename... Args>
  120. optional<T>::optional(cm::in_place_t, Args&&... args)
  121. {
  122. this->emplace(std::forward<Args>(args)...);
  123. }
  124. template <typename T>
  125. template <typename U, typename>
  126. optional<T>::optional(U&& v)
  127. {
  128. this->emplace(std::forward<U>(v));
  129. }
  130. template <typename T>
  131. optional<T>::~optional()
  132. {
  133. this->reset();
  134. }
  135. template <typename T>
  136. optional<T>& optional<T>::operator=(nullopt_t) noexcept
  137. {
  138. this->reset();
  139. return *this;
  140. }
  141. template <typename T>
  142. optional<T>& optional<T>::operator=(const optional& other)
  143. {
  144. if (other.has_value()) {
  145. if (this->has_value()) {
  146. this->value() = *other;
  147. } else {
  148. this->emplace(*other);
  149. }
  150. } else {
  151. this->reset();
  152. }
  153. return *this;
  154. }
  155. template <typename T>
  156. optional<T>& optional<T>::operator=(optional&& other) noexcept
  157. {
  158. if (other.has_value()) {
  159. if (this->has_value()) {
  160. this->value() = std::move(*other);
  161. } else {
  162. this->emplace(std::move(*other));
  163. }
  164. } else {
  165. this->reset();
  166. }
  167. return *this;
  168. }
  169. template <typename T>
  170. template <typename U, typename>
  171. optional<T>& optional<T>::operator=(U&& v)
  172. {
  173. if (this->has_value()) {
  174. this->value() = v;
  175. } else {
  176. this->emplace(std::forward<U>(v));
  177. }
  178. return *this;
  179. }
  180. template <typename T, typename U>
  181. bool operator==(const optional<T>& lhs, const optional<U>& rhs)
  182. {
  183. if (lhs.has_value()) {
  184. return rhs.has_value() && *lhs == *rhs;
  185. }
  186. return !rhs.has_value();
  187. }
  188. template <typename T, typename U>
  189. bool operator!=(const optional<T>& lhs, const optional<U>& rhs)
  190. {
  191. if (lhs.has_value()) {
  192. return !rhs.has_value() || *lhs != *rhs;
  193. }
  194. return rhs.has_value();
  195. }
  196. template <typename T, typename U>
  197. bool operator<(const optional<T>& lhs, const optional<U>& rhs)
  198. {
  199. if (rhs.has_value()) {
  200. return !lhs.has_value() || *lhs < *rhs;
  201. }
  202. return false;
  203. }
  204. template <typename T, typename U>
  205. bool operator<=(const optional<T>& lhs, const optional<U>& rhs)
  206. {
  207. if (!lhs.has_value()) {
  208. return true;
  209. }
  210. if (rhs.has_value()) {
  211. return *lhs <= *rhs;
  212. }
  213. return false;
  214. }
  215. template <typename T, typename U>
  216. bool operator>(const optional<T>& lhs, const optional<U>& rhs)
  217. {
  218. if (lhs.has_value()) {
  219. return !rhs.has_value() || *lhs > *rhs;
  220. }
  221. return false;
  222. }
  223. template <typename T, typename U>
  224. bool operator>=(const optional<T>& lhs, const optional<U>& rhs)
  225. {
  226. if (!rhs.has_value()) {
  227. return true;
  228. }
  229. if (lhs.has_value()) {
  230. return *lhs >= *rhs;
  231. }
  232. return false;
  233. }
  234. template <typename T>
  235. bool operator==(const optional<T>& opt, nullopt_t) noexcept
  236. {
  237. return !opt.has_value();
  238. }
  239. template <typename T>
  240. bool operator!=(const optional<T>& opt, nullopt_t) noexcept
  241. {
  242. return opt.has_value();
  243. }
  244. template <typename T>
  245. bool operator<(const optional<T>& opt, nullopt_t) noexcept
  246. {
  247. return false;
  248. }
  249. template <typename T>
  250. bool operator<=(const optional<T>& opt, nullopt_t) noexcept
  251. {
  252. return !opt.has_value();
  253. }
  254. template <typename T>
  255. bool operator>(const optional<T>& opt, nullopt_t) noexcept
  256. {
  257. return opt.has_value();
  258. }
  259. template <typename T>
  260. bool operator>=(const optional<T>& opt, nullopt_t) noexcept
  261. {
  262. return true;
  263. }
  264. template <typename T>
  265. bool operator==(nullopt_t, const optional<T>& opt) noexcept
  266. {
  267. return !opt.has_value();
  268. }
  269. template <typename T>
  270. bool operator!=(nullopt_t, const optional<T>& opt) noexcept
  271. {
  272. return opt.has_value();
  273. }
  274. template <typename T>
  275. bool operator<(nullopt_t, const optional<T>& opt) noexcept
  276. {
  277. return opt.has_value();
  278. }
  279. template <typename T>
  280. bool operator<=(nullopt_t, const optional<T>& opt) noexcept
  281. {
  282. return true;
  283. }
  284. template <typename T>
  285. bool operator>(nullopt_t, const optional<T>& opt) noexcept
  286. {
  287. return false;
  288. }
  289. template <typename T>
  290. bool operator>=(nullopt_t, const optional<T>& opt) noexcept
  291. {
  292. return !opt.has_value();
  293. }
  294. template <typename T, typename U>
  295. bool operator==(const optional<T>& opt, const U& value)
  296. {
  297. return opt.has_value() && *opt == value;
  298. }
  299. template <typename T, typename U>
  300. bool operator!=(const optional<T>& opt, const U& value)
  301. {
  302. return !opt.has_value() || *opt != value;
  303. }
  304. template <typename T, typename U>
  305. bool operator<(const optional<T>& opt, const U& value)
  306. {
  307. return !opt.has_value() || *opt < value;
  308. }
  309. template <typename T, typename U>
  310. bool operator<=(const optional<T>& opt, const U& value)
  311. {
  312. return !opt.has_value() || *opt <= value;
  313. }
  314. template <typename T, typename U>
  315. bool operator>(const optional<T>& opt, const U& value)
  316. {
  317. return opt.has_value() && *opt > value;
  318. }
  319. template <typename T, typename U>
  320. bool operator>=(const optional<T>& opt, const U& value)
  321. {
  322. return opt.has_value() && *opt >= value;
  323. }
  324. template <typename T, typename U>
  325. bool operator==(const T& value, const optional<U>& opt)
  326. {
  327. return opt.has_value() && value == *opt;
  328. }
  329. template <typename T, typename U>
  330. bool operator!=(const T& value, const optional<U>& opt)
  331. {
  332. return !opt.has_value() || value != *opt;
  333. }
  334. template <typename T, typename U>
  335. bool operator<(const T& value, const optional<U>& opt)
  336. {
  337. return opt.has_value() && value < *opt;
  338. }
  339. template <typename T, typename U>
  340. bool operator<=(const T& value, const optional<U>& opt)
  341. {
  342. return opt.has_value() && value <= *opt;
  343. }
  344. template <typename T, typename U>
  345. bool operator>(const T& value, const optional<U>& opt)
  346. {
  347. return !opt.has_value() || value > *opt;
  348. }
  349. template <typename T, typename U>
  350. bool operator>=(const T& value, const optional<U>& opt)
  351. {
  352. return !opt.has_value() || value >= *opt;
  353. }
  354. template <typename T>
  355. const T* optional<T>::operator->() const
  356. {
  357. return &**this;
  358. }
  359. template <typename T>
  360. T* optional<T>::operator->()
  361. {
  362. return &**this;
  363. }
  364. template <typename T>
  365. const T& optional<T>::operator*() const&
  366. {
  367. return this->_mem.value;
  368. }
  369. template <typename T>
  370. T& optional<T>::operator*() &
  371. {
  372. return this->_mem.value;
  373. }
  374. template <typename T>
  375. const T&& optional<T>::operator*() const&&
  376. {
  377. return std::move(**this);
  378. }
  379. template <typename T>
  380. T&& optional<T>::operator*() &&
  381. {
  382. return std::move(**this);
  383. }
  384. template <typename T>
  385. bool optional<T>::has_value() const noexcept
  386. {
  387. return this->_has_value;
  388. }
  389. template <typename T>
  390. optional<T>::operator bool() const noexcept
  391. {
  392. return this->has_value();
  393. }
  394. template <typename T>
  395. T& optional<T>::value() &
  396. {
  397. if (!this->has_value()) {
  398. throw cm::bad_optional_access{};
  399. }
  400. return **this;
  401. }
  402. template <typename T>
  403. const T& optional<T>::value() const&
  404. {
  405. if (!this->has_value()) {
  406. throw cm::bad_optional_access{};
  407. }
  408. return **this;
  409. }
  410. template <typename T>
  411. template <typename U>
  412. T optional<T>::value_or(U&& default_value) const&
  413. {
  414. return bool(*this) ? **this : static_cast<T>(std::forward<U>(default_value));
  415. }
  416. template <typename T>
  417. template <typename U>
  418. T optional<T>::value_or(U&& default_value) &&
  419. {
  420. return bool(*this) ? std::move(**this)
  421. : static_cast<T>(std::forward<U>(default_value));
  422. }
  423. template <typename T>
  424. void optional<T>::swap(optional& other) noexcept
  425. {
  426. if (this->has_value()) {
  427. if (other.has_value()) {
  428. using std::swap;
  429. swap(**this, *other);
  430. } else {
  431. other.emplace(std::move(**this));
  432. this->reset();
  433. }
  434. } else if (other.has_value()) {
  435. this->emplace(std::move(*other));
  436. other.reset();
  437. }
  438. }
  439. template <typename T>
  440. void optional<T>::reset() noexcept
  441. {
  442. if (this->has_value()) {
  443. this->_has_value = false;
  444. std::allocator_traits<std::allocator<T>>::destroy(this->_allocator,
  445. &**this);
  446. }
  447. }
  448. template <typename T>
  449. template <typename... Args>
  450. T& optional<T>::emplace(Args&&... args)
  451. {
  452. this->reset();
  453. std::allocator_traits<std::allocator<T>>::construct(
  454. this->_allocator, &**this, std::forward<Args>(args)...);
  455. this->_has_value = true;
  456. return this->value();
  457. }
  458. #endif
  459. }