optional 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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. template <typename U = T>
  55. typename std::enable_if<std::is_constructible<T, U&&>::value &&
  56. std::is_assignable<T&, U&&>::value,
  57. optional&>::type
  58. operator=(optional<U>&& other) noexcept;
  59. template <typename U = T>
  60. typename std::enable_if<
  61. !std::is_same<typename std::decay<U>::type, cm::optional<T>>::value &&
  62. std::is_constructible<T, U&&>::value &&
  63. std::is_assignable<T&, U&&>::value &&
  64. (!std::is_scalar<T>::value ||
  65. !std::is_same<typename std::decay<U>::type, T>::value),
  66. optional&>::type
  67. operator=(U&& v);
  68. const T* operator->() const;
  69. T* operator->();
  70. const T& operator*() const&;
  71. T& operator*() &;
  72. const T&& operator*() const&&;
  73. T&& operator*() &&;
  74. explicit operator bool() const noexcept;
  75. bool has_value() const noexcept;
  76. T& value() &;
  77. const T& value() const&;
  78. T&& value() &&;
  79. const T&& value() const&&;
  80. template <typename U>
  81. T value_or(U&& default_value) const&;
  82. template <typename U>
  83. T value_or(U&& default_value) &&;
  84. void swap(optional& other) noexcept;
  85. void reset() noexcept;
  86. template <typename... Args>
  87. T& emplace(Args&&... args);
  88. private:
  89. bool _has_value = false;
  90. std::allocator<T> _allocator;
  91. union _mem_union
  92. {
  93. T value;
  94. // Explicit constructor and destructor is required to make this work
  95. _mem_union() noexcept {}
  96. ~_mem_union() noexcept {}
  97. } _mem;
  98. };
  99. template <typename T>
  100. optional<typename std::decay<T>::type> make_optional(T&& value)
  101. {
  102. return optional<typename std::decay<T>::type>(std::forward<T>(value));
  103. }
  104. template <typename T, class... Args>
  105. optional<T> make_optional(Args&&... args)
  106. {
  107. return optional<T>(in_place, std::forward<Args>(args)...);
  108. }
  109. template <typename T>
  110. optional<T>::optional(nullopt_t) noexcept
  111. : optional()
  112. {
  113. }
  114. template <typename T>
  115. optional<T>::optional(const optional& other)
  116. {
  117. if (other.has_value()) {
  118. this->emplace(*other);
  119. }
  120. }
  121. template <typename T>
  122. optional<T>::optional(optional&& other) noexcept
  123. {
  124. if (other.has_value()) {
  125. this->emplace(std::move(*other));
  126. }
  127. }
  128. template <typename T>
  129. template <typename... Args>
  130. optional<T>::optional(cm::in_place_t, Args&&... args)
  131. {
  132. this->emplace(std::forward<Args>(args)...);
  133. }
  134. template <typename T>
  135. template <typename U, typename>
  136. optional<T>::optional(U&& v)
  137. {
  138. this->emplace(std::forward<U>(v));
  139. }
  140. template <typename T>
  141. optional<T>::~optional()
  142. {
  143. this->reset();
  144. }
  145. template <typename T>
  146. optional<T>& optional<T>::operator=(nullopt_t) noexcept
  147. {
  148. this->reset();
  149. return *this;
  150. }
  151. template <typename T>
  152. optional<T>& optional<T>::operator=(const optional& other)
  153. {
  154. if (other.has_value()) {
  155. if (this->has_value()) {
  156. this->value() = *other;
  157. } else {
  158. this->emplace(*other);
  159. }
  160. } else {
  161. this->reset();
  162. }
  163. return *this;
  164. }
  165. template <typename T>
  166. template <typename U>
  167. typename std::enable_if<std::is_constructible<T, U&&>::value &&
  168. std::is_assignable<T&, U&&>::value,
  169. optional<T>&>::type
  170. optional<T>::operator=(optional<U>&& other) noexcept
  171. {
  172. if (other.has_value()) {
  173. if (this->has_value()) {
  174. this->value() = std::move(*other);
  175. } else {
  176. this->emplace(std::move(*other));
  177. }
  178. } else {
  179. this->reset();
  180. }
  181. return *this;
  182. }
  183. template <typename T>
  184. template <typename U>
  185. typename std::enable_if<
  186. !std::is_same<typename std::decay<U>::type, cm::optional<T>>::value &&
  187. std::is_constructible<T, U&&>::value &&
  188. std::is_assignable<T&, U&&>::value &&
  189. (!std::is_scalar<T>::value ||
  190. !std::is_same<typename std::decay<U>::type, T>::value),
  191. optional<T>&>::type
  192. optional<T>::operator=(U&& v)
  193. {
  194. if (this->has_value()) {
  195. this->value() = v;
  196. } else {
  197. this->emplace(std::forward<U>(v));
  198. }
  199. return *this;
  200. }
  201. template <typename T, typename U>
  202. bool operator==(const optional<T>& lhs, const optional<U>& rhs)
  203. {
  204. if (lhs.has_value()) {
  205. return rhs.has_value() && *lhs == *rhs;
  206. }
  207. return !rhs.has_value();
  208. }
  209. template <typename T, typename U>
  210. bool operator!=(const optional<T>& lhs, const optional<U>& rhs)
  211. {
  212. if (lhs.has_value()) {
  213. return !rhs.has_value() || *lhs != *rhs;
  214. }
  215. return rhs.has_value();
  216. }
  217. template <typename T, typename U>
  218. bool operator<(const optional<T>& lhs, const optional<U>& rhs)
  219. {
  220. if (rhs.has_value()) {
  221. return !lhs.has_value() || *lhs < *rhs;
  222. }
  223. return false;
  224. }
  225. template <typename T, typename U>
  226. bool operator<=(const optional<T>& lhs, const optional<U>& rhs)
  227. {
  228. if (!lhs.has_value()) {
  229. return true;
  230. }
  231. if (rhs.has_value()) {
  232. return *lhs <= *rhs;
  233. }
  234. return false;
  235. }
  236. template <typename T, typename U>
  237. bool operator>(const optional<T>& lhs, const optional<U>& rhs)
  238. {
  239. if (lhs.has_value()) {
  240. return !rhs.has_value() || *lhs > *rhs;
  241. }
  242. return false;
  243. }
  244. template <typename T, typename U>
  245. bool operator>=(const optional<T>& lhs, const optional<U>& rhs)
  246. {
  247. if (!rhs.has_value()) {
  248. return true;
  249. }
  250. if (lhs.has_value()) {
  251. return *lhs >= *rhs;
  252. }
  253. return false;
  254. }
  255. template <typename T>
  256. bool operator==(const optional<T>& opt, nullopt_t) noexcept
  257. {
  258. return !opt.has_value();
  259. }
  260. template <typename T>
  261. bool operator!=(const optional<T>& opt, nullopt_t) noexcept
  262. {
  263. return opt.has_value();
  264. }
  265. template <typename T>
  266. bool operator<(const optional<T>& /*opt*/, nullopt_t) noexcept
  267. {
  268. return false;
  269. }
  270. template <typename T>
  271. bool operator<=(const optional<T>& opt, nullopt_t) noexcept
  272. {
  273. return !opt.has_value();
  274. }
  275. template <typename T>
  276. bool operator>(const optional<T>& opt, nullopt_t) noexcept
  277. {
  278. return opt.has_value();
  279. }
  280. template <typename T>
  281. bool operator>=(const optional<T>& /*opt*/, nullopt_t) noexcept
  282. {
  283. return true;
  284. }
  285. template <typename T>
  286. bool operator==(nullopt_t, const optional<T>& opt) noexcept
  287. {
  288. return !opt.has_value();
  289. }
  290. template <typename T>
  291. bool operator!=(nullopt_t, const optional<T>& opt) noexcept
  292. {
  293. return opt.has_value();
  294. }
  295. template <typename T>
  296. bool operator<(nullopt_t, const optional<T>& opt) noexcept
  297. {
  298. return opt.has_value();
  299. }
  300. template <typename T>
  301. bool operator<=(nullopt_t, const optional<T>& /*opt*/) noexcept
  302. {
  303. return true;
  304. }
  305. template <typename T>
  306. bool operator>(nullopt_t, const optional<T>& /*opt*/) noexcept
  307. {
  308. return false;
  309. }
  310. template <typename T>
  311. bool operator>=(nullopt_t, const optional<T>& opt) noexcept
  312. {
  313. return !opt.has_value();
  314. }
  315. template <typename T, typename U>
  316. bool operator==(const optional<T>& opt, const U& value)
  317. {
  318. return opt.has_value() && *opt == value;
  319. }
  320. template <typename T, typename U>
  321. bool operator!=(const optional<T>& opt, const U& value)
  322. {
  323. return !opt.has_value() || *opt != value;
  324. }
  325. template <typename T, typename U>
  326. bool operator<(const optional<T>& opt, const U& value)
  327. {
  328. return !opt.has_value() || *opt < value;
  329. }
  330. template <typename T, typename U>
  331. bool operator<=(const optional<T>& opt, const U& value)
  332. {
  333. return !opt.has_value() || *opt <= value;
  334. }
  335. template <typename T, typename U>
  336. bool operator>(const optional<T>& opt, const U& value)
  337. {
  338. return opt.has_value() && *opt > value;
  339. }
  340. template <typename T, typename U>
  341. bool operator>=(const optional<T>& opt, const U& value)
  342. {
  343. return opt.has_value() && *opt >= value;
  344. }
  345. template <typename T, typename U>
  346. bool operator==(const T& value, const optional<U>& opt)
  347. {
  348. return opt.has_value() && value == *opt;
  349. }
  350. template <typename T, typename U>
  351. bool operator!=(const T& value, const optional<U>& opt)
  352. {
  353. return !opt.has_value() || value != *opt;
  354. }
  355. template <typename T, typename U>
  356. bool operator<(const T& value, const optional<U>& opt)
  357. {
  358. return opt.has_value() && value < *opt;
  359. }
  360. template <typename T, typename U>
  361. bool operator<=(const T& value, const optional<U>& opt)
  362. {
  363. return opt.has_value() && value <= *opt;
  364. }
  365. template <typename T, typename U>
  366. bool operator>(const T& value, const optional<U>& opt)
  367. {
  368. return !opt.has_value() || value > *opt;
  369. }
  370. template <typename T, typename U>
  371. bool operator>=(const T& value, const optional<U>& opt)
  372. {
  373. return !opt.has_value() || value >= *opt;
  374. }
  375. template <typename T>
  376. const T* optional<T>::operator->() const
  377. {
  378. return &**this;
  379. }
  380. template <typename T>
  381. T* optional<T>::operator->()
  382. {
  383. return &**this;
  384. }
  385. template <typename T>
  386. const T& optional<T>::operator*() const&
  387. {
  388. return this->_mem.value;
  389. }
  390. template <typename T>
  391. T& optional<T>::operator*() &
  392. {
  393. return this->_mem.value;
  394. }
  395. template <typename T>
  396. const T&& optional<T>::operator*() const&&
  397. {
  398. return std::move(**this);
  399. }
  400. template <typename T>
  401. T&& optional<T>::operator*() &&
  402. {
  403. return std::move(**this);
  404. }
  405. template <typename T>
  406. bool optional<T>::has_value() const noexcept
  407. {
  408. return this->_has_value;
  409. }
  410. template <typename T>
  411. optional<T>::operator bool() const noexcept
  412. {
  413. return this->has_value();
  414. }
  415. template <typename T>
  416. T& optional<T>::value() &
  417. {
  418. if (!this->has_value()) {
  419. throw cm::bad_optional_access{};
  420. }
  421. return **this;
  422. }
  423. template <typename T>
  424. const T& optional<T>::value() const&
  425. {
  426. if (!this->has_value()) {
  427. throw cm::bad_optional_access{};
  428. }
  429. return **this;
  430. }
  431. template <typename T>
  432. template <typename U>
  433. T optional<T>::value_or(U&& default_value) const&
  434. {
  435. return bool(*this) ? **this : static_cast<T>(std::forward<U>(default_value));
  436. }
  437. template <typename T>
  438. template <typename U>
  439. T optional<T>::value_or(U&& default_value) &&
  440. {
  441. return bool(*this) ? std::move(**this)
  442. : static_cast<T>(std::forward<U>(default_value));
  443. }
  444. template <typename T>
  445. void optional<T>::swap(optional& other) noexcept
  446. {
  447. if (this->has_value()) {
  448. if (other.has_value()) {
  449. using std::swap;
  450. swap(**this, *other);
  451. } else {
  452. other.emplace(std::move(**this));
  453. this->reset();
  454. }
  455. } else if (other.has_value()) {
  456. this->emplace(std::move(*other));
  457. other.reset();
  458. }
  459. }
  460. template <typename T>
  461. void optional<T>::reset() noexcept
  462. {
  463. if (this->has_value()) {
  464. this->_has_value = false;
  465. std::allocator_traits<std::allocator<T>>::destroy(this->_allocator,
  466. &**this);
  467. }
  468. }
  469. template <typename T>
  470. template <typename... Args>
  471. T& optional<T>::emplace(Args&&... args)
  472. {
  473. this->reset();
  474. std::allocator_traits<std::allocator<T>>::construct(
  475. this->_allocator, &**this, std::forward<Args>(args)...);
  476. this->_has_value = true;
  477. return this->value();
  478. }
  479. #endif
  480. }