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.

949 lines
36KB

  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Casey Carter 2017
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_UTILITY_OPTIONAL_HPP
  14. #define RANGES_V3_UTILITY_OPTIONAL_HPP
  15. #include <exception>
  16. #include <initializer_list>
  17. #include <memory>
  18. #include <new>
  19. #include <concepts/concepts.hpp>
  20. #include <range/v3/detail/config.hpp>
  21. #include <range/v3/utility/addressof.hpp>
  22. #include <range/v3/utility/in_place.hpp>
  23. #include <range/v3/utility/static_const.hpp>
  24. #include <range/v3/utility/swap.hpp>
  25. namespace ranges
  26. {
  27. template<typename>
  28. struct optional;
  29. struct bad_optional_access : std::exception
  30. {
  31. virtual const char * what() const noexcept override
  32. {
  33. return "bad optional access";
  34. }
  35. };
  36. struct nullopt_t
  37. {
  38. struct tag
  39. {};
  40. explicit constexpr nullopt_t(tag) noexcept
  41. {}
  42. };
  43. #if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
  44. inline constexpr nullopt_t nullopt{nullopt_t::tag{}};
  45. #else
  46. /// \cond
  47. namespace detail
  48. {
  49. template<typename>
  50. struct nullopt_holder
  51. {
  52. static constexpr nullopt_t nullopt{nullopt_t::tag{}};
  53. };
  54. template<typename T>
  55. constexpr nullopt_t nullopt_holder<T>::nullopt;
  56. } // namespace detail
  57. /// \endcond
  58. namespace
  59. {
  60. constexpr auto & nullopt = detail::nullopt_holder<void>::nullopt;
  61. }
  62. #endif
  63. /// \cond
  64. namespace detail
  65. {
  66. template<typename = void>
  67. [[noreturn]] bool throw_bad_optional_access()
  68. {
  69. throw bad_optional_access{};
  70. }
  71. namespace optional_adl
  72. {
  73. template<typename T, bool = std::is_trivially_destructible<T>::value>
  74. struct optional_storage
  75. {
  76. union
  77. {
  78. char dummy_;
  79. meta::_t<std::remove_cv<T>> data_;
  80. };
  81. bool engaged_;
  82. constexpr optional_storage() noexcept
  83. : optional_storage(
  84. tag{},
  85. meta::strict_and<detail::is_trivially_default_constructible<T>,
  86. detail::is_trivially_copyable<T>>{})
  87. {}
  88. CPP_template(typename... Args)( //
  89. requires constructible_from<T, Args...>) //
  90. constexpr explicit optional_storage(in_place_t,
  91. Args &&... args) //
  92. noexcept(std::is_nothrow_constructible<T, Args...>::value)
  93. : data_(static_cast<Args &&>(args)...)
  94. , engaged_{true}
  95. {}
  96. constexpr void reset() noexcept
  97. {
  98. engaged_ = false;
  99. }
  100. private:
  101. struct tag
  102. {};
  103. constexpr optional_storage(tag, std::false_type) noexcept
  104. : dummy_{}
  105. , engaged_{false}
  106. {}
  107. constexpr optional_storage(tag, std::true_type) noexcept
  108. : data_{}
  109. , engaged_{false}
  110. {}
  111. };
  112. template<typename T>
  113. struct optional_storage<T, false>
  114. {
  115. union
  116. {
  117. char dummy_;
  118. meta::_t<std::remove_cv<T>> data_;
  119. };
  120. bool engaged_;
  121. ~optional_storage()
  122. {
  123. reset();
  124. }
  125. constexpr optional_storage() noexcept
  126. : dummy_{}
  127. , engaged_{false}
  128. {}
  129. CPP_template(typename... Args)( //
  130. requires constructible_from<T, Args...>) //
  131. constexpr explicit optional_storage(in_place_t,
  132. Args &&... args) //
  133. noexcept(std::is_nothrow_constructible<T, Args...>::value)
  134. : data_(static_cast<Args &&>(args)...)
  135. , engaged_{true}
  136. {}
  137. optional_storage(optional_storage const &) = default;
  138. optional_storage(optional_storage &&) = default;
  139. optional_storage & operator=(optional_storage const &) = default;
  140. optional_storage & operator=(optional_storage &&) = default;
  141. void reset() noexcept
  142. {
  143. if(engaged_)
  144. {
  145. data_.~T();
  146. engaged_ = false;
  147. }
  148. }
  149. };
  150. template<typename T>
  151. struct optional_base : private optional_storage<T>
  152. {
  153. using optional_storage<T>::optional_storage;
  154. using optional_storage<T>::reset;
  155. constexpr bool has_value() const noexcept
  156. {
  157. return engaged_;
  158. }
  159. constexpr T & operator*() & noexcept
  160. {
  161. return RANGES_EXPECT(engaged_), data_;
  162. }
  163. constexpr T const & operator*() const & noexcept
  164. {
  165. return RANGES_EXPECT(engaged_), data_;
  166. }
  167. constexpr T && operator*() && noexcept
  168. {
  169. return RANGES_EXPECT(engaged_), detail::move(data_);
  170. }
  171. constexpr T const && operator*() const && noexcept
  172. {
  173. return RANGES_EXPECT(engaged_), detail::move(data_);
  174. }
  175. constexpr T * operator->() noexcept
  176. {
  177. return RANGES_EXPECT(engaged_), detail::addressof(data_);
  178. }
  179. constexpr T const * operator->() const noexcept
  180. {
  181. return RANGES_EXPECT(engaged_), detail::addressof(data_);
  182. }
  183. CPP_member
  184. constexpr auto swap(optional_base & that) noexcept(
  185. std::is_nothrow_move_constructible<T>::value &&
  186. is_nothrow_swappable<T>::value) -> CPP_ret(void)( //
  187. requires move_constructible<T> && swappable<T>)
  188. {
  189. constexpr bool can_swap_trivially =
  190. !::concepts::adl_swap_detail::is_adl_swappable_v<T> &&
  191. detail::is_trivially_move_constructible<T>::value &&
  192. detail::is_trivially_move_assignable<T>::value;
  193. swap_(meta::bool_<can_swap_trivially>{}, that);
  194. }
  195. protected:
  196. template<typename... Args>
  197. auto construct_from(Args &&... args) noexcept(
  198. std::is_nothrow_constructible<T, Args...>::value) -> CPP_ret(T &)( //
  199. requires constructible_from<T, Args...>)
  200. {
  201. RANGES_EXPECT(!engaged_);
  202. auto const address = static_cast<void *>(std::addressof(data_));
  203. ::new(address) T(static_cast<Args &&>(args)...);
  204. engaged_ = true;
  205. return data_;
  206. }
  207. template<typename U>
  208. constexpr void assign_from(U && that) noexcept(
  209. std::is_nothrow_constructible<T, decltype(*static_cast<U &&>(that))>::
  210. value && std::is_nothrow_assignable<
  211. T &, decltype(*static_cast<U &&>(that))>::value)
  212. {
  213. if(!that.has_value())
  214. reset();
  215. else if(engaged_)
  216. data_ = *static_cast<U &&>(that);
  217. else
  218. {
  219. auto const address =
  220. static_cast<void *>(detail::addressof(data_));
  221. ::new(address) T(*static_cast<U &&>(that));
  222. engaged_ = true;
  223. }
  224. }
  225. private:
  226. constexpr void swap_(std::true_type, optional_base & that) noexcept
  227. {
  228. ranges::swap(static_cast<optional_storage<T> &>(*this),
  229. static_cast<optional_storage<T> &>(that));
  230. }
  231. constexpr void swap_(std::false_type, optional_base & that) noexcept(
  232. std::is_nothrow_move_constructible<T>::value &&
  233. is_nothrow_swappable<T>::value)
  234. {
  235. if(that.engaged_ == engaged_)
  236. {
  237. if(engaged_)
  238. ranges::swap(data_, that.data_);
  239. }
  240. else
  241. {
  242. auto & src = engaged_ ? *this : that;
  243. auto & dst = engaged_ ? that : *this;
  244. dst.construct_from(detail::move(src.data_));
  245. src.reset();
  246. }
  247. }
  248. using optional_storage<T>::engaged_;
  249. using optional_storage<T>::data_;
  250. };
  251. template<typename T>
  252. struct optional_base<T &>
  253. {
  254. optional_base() = default;
  255. template<typename Arg>
  256. constexpr explicit CPP_ctor(optional_base)(in_place_t, Arg && arg)( //
  257. noexcept(true) //
  258. requires constructible_from<T &, Arg>)
  259. : ptr_(detail::addressof(arg))
  260. {}
  261. constexpr bool has_value() const noexcept
  262. {
  263. return ptr_;
  264. }
  265. constexpr T & operator*() const noexcept
  266. {
  267. return RANGES_EXPECT(ptr_), *ptr_;
  268. }
  269. constexpr T * operator->() const noexcept
  270. {
  271. return RANGES_EXPECT(ptr_), ptr_;
  272. }
  273. constexpr void reset() noexcept
  274. {
  275. ptr_ = nullptr;
  276. }
  277. CPP_member
  278. constexpr auto swap(optional_base & that) noexcept(
  279. is_nothrow_swappable<T>::value) -> CPP_ret(void)( //
  280. requires swappable<T>)
  281. {
  282. if(ptr_ && that.ptr_)
  283. ranges::swap(*ptr_, *that.ptr_);
  284. else
  285. ranges::swap(ptr_, that.ptr_);
  286. }
  287. protected:
  288. template<typename U>
  289. constexpr auto construct_from(U && ref) noexcept -> CPP_ret(T &)( //
  290. requires convertible_to<U &, T &>)
  291. {
  292. RANGES_EXPECT(!ptr_);
  293. ptr_ = detail::addressof(ref);
  294. return *ptr_;
  295. }
  296. template<typename U>
  297. constexpr void assign_from(U && that)
  298. {
  299. if(ptr_ && that.ptr_)
  300. *ptr_ = *that.ptr_;
  301. else
  302. ptr_ = that.ptr_;
  303. }
  304. private:
  305. T * ptr_ = nullptr;
  306. };
  307. template<typename T>
  308. struct optional_copy : optional_base<T>
  309. {
  310. optional_copy() = default;
  311. optional_copy(optional_copy const & that) noexcept(
  312. std::is_nothrow_copy_constructible<T>::value)
  313. {
  314. if(that.has_value())
  315. this->construct_from(*that);
  316. }
  317. optional_copy(optional_copy &&) = default;
  318. optional_copy & operator=(optional_copy const &) = default;
  319. optional_copy & operator=(optional_copy &&) = default;
  320. using optional_base<T>::optional_base;
  321. };
  322. template<typename T>
  323. using copy_construct_layer =
  324. meta::if_c<std::is_copy_constructible<T>::value &&
  325. !detail::is_trivially_copy_constructible<T>::value,
  326. optional_copy<T>, optional_base<T>>;
  327. template<typename T>
  328. struct optional_move : copy_construct_layer<T>
  329. {
  330. optional_move() = default;
  331. optional_move(optional_move const &) = default;
  332. optional_move(optional_move && that) noexcept(
  333. std::is_nothrow_move_constructible<T>::value)
  334. {
  335. if(that.has_value())
  336. this->construct_from(std::move(*that));
  337. }
  338. optional_move & operator=(optional_move const &) = default;
  339. optional_move & operator=(optional_move &&) = default;
  340. using copy_construct_layer<T>::copy_construct_layer;
  341. };
  342. template<typename T>
  343. using move_construct_layer =
  344. meta::if_c<std::is_move_constructible<T>::value &&
  345. !detail::is_trivially_move_constructible<T>::value,
  346. optional_move<T>, copy_construct_layer<T>>;
  347. template<typename T>
  348. struct optional_copy_assign : move_construct_layer<T>
  349. {
  350. optional_copy_assign() = default;
  351. optional_copy_assign(optional_copy_assign const &) = default;
  352. optional_copy_assign(optional_copy_assign &&) = default;
  353. optional_copy_assign & operator=(optional_copy_assign const & that) //
  354. noexcept(std::is_nothrow_copy_constructible<T>::value &&
  355. std::is_nothrow_copy_assignable<T>::value)
  356. {
  357. this->assign_from(that);
  358. return *this;
  359. }
  360. optional_copy_assign & operator=(optional_copy_assign &&) = default;
  361. using move_construct_layer<T>::move_construct_layer;
  362. };
  363. template<typename T>
  364. struct deleted_copy_assign : move_construct_layer<T>
  365. {
  366. deleted_copy_assign() = default;
  367. deleted_copy_assign(deleted_copy_assign const &) = default;
  368. deleted_copy_assign(deleted_copy_assign &&) = default;
  369. deleted_copy_assign & operator=(deleted_copy_assign const &) = delete;
  370. deleted_copy_assign & operator=(deleted_copy_assign &&) = default;
  371. using move_construct_layer<T>::move_construct_layer;
  372. };
  373. template<typename T>
  374. using copy_assign_layer = meta::if_c<
  375. std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
  376. meta::if_c<std::is_reference<T>::value ||
  377. !(detail::is_trivially_copy_constructible<T>::value &&
  378. detail::is_trivially_copy_assignable<T>::value),
  379. optional_copy_assign<T>, move_construct_layer<T>>,
  380. deleted_copy_assign<T>>;
  381. template<typename T>
  382. struct optional_move_assign : copy_assign_layer<T>
  383. {
  384. optional_move_assign() = default;
  385. optional_move_assign(optional_move_assign const &) = default;
  386. optional_move_assign(optional_move_assign &&) = default;
  387. optional_move_assign & operator=(optional_move_assign const &) = default;
  388. optional_move_assign & operator=(optional_move_assign && that) noexcept(
  389. std::is_nothrow_move_constructible<T>::value &&
  390. std::is_nothrow_move_assignable<T>::value)
  391. {
  392. this->assign_from(std::move(that));
  393. return *this;
  394. }
  395. using copy_assign_layer<T>::copy_assign_layer;
  396. };
  397. template<typename T>
  398. struct deleted_move_assign : copy_assign_layer<T>
  399. {
  400. deleted_move_assign() = default;
  401. deleted_move_assign(deleted_move_assign const &) = default;
  402. deleted_move_assign(deleted_move_assign &&) = default;
  403. deleted_move_assign & operator=(deleted_move_assign const &) = default;
  404. deleted_move_assign & operator=(deleted_move_assign &&) = delete;
  405. using copy_assign_layer<T>::copy_assign_layer;
  406. };
  407. template<typename T>
  408. using move_assign_layer = meta::if_c<
  409. std::is_move_constructible<T>::value && std::is_move_assignable<T>::value,
  410. meta::if_c<std::is_reference<T>::value ||
  411. !(detail::is_trivially_move_constructible<T>::value &&
  412. detail::is_trivially_move_assignable<T>::value),
  413. optional_move_assign<T>, copy_assign_layer<T>>,
  414. deleted_move_assign<T>>;
  415. } // namespace optional_adl
  416. } // namespace detail
  417. /// \endcond
  418. // clang-format off
  419. CPP_def
  420. (
  421. template(typename U, typename T)
  422. concept optional_should_convert,
  423. requires(int)(void()) && !(
  424. constructible_from<T, optional<U> & > ||
  425. constructible_from<T, optional<U> && > ||
  426. constructible_from<T, optional<U> const & > ||
  427. constructible_from<T, optional<U> const &&> ||
  428. convertible_to<optional<U> &, T> ||
  429. convertible_to<optional<U> &&, T> ||
  430. convertible_to<optional<U> const &, T> ||
  431. convertible_to<optional<U> const &&, T>
  432. )
  433. );
  434. CPP_def
  435. (
  436. template(typename U, typename T)
  437. concept optional_should_convert_assign,
  438. optional_should_convert<U, T> &&
  439. !(assignable_from<T &, optional<U> &> ||
  440. assignable_from<T &, optional<U> &&> ||
  441. assignable_from<T &, optional<U> const &> ||
  442. assignable_from<T &, optional<U> const &&>)
  443. );
  444. // clang-format on
  445. template<typename T>
  446. struct optional : detail::optional_adl::move_assign_layer<T>
  447. {
  448. private:
  449. using base_t = detail::optional_adl::move_assign_layer<T>;
  450. public:
  451. CPP_assert(destructible<T>);
  452. static_assert(std::is_object<T>::value || std::is_lvalue_reference<T>::value, "");
  453. static_assert((bool)!same_as<nullopt_t, uncvref_t<T>>, "");
  454. static_assert((bool)!same_as<in_place_t, uncvref_t<T>>, "");
  455. using value_type = meta::_t<std::remove_cv<T>>;
  456. constexpr optional() noexcept
  457. {}
  458. constexpr optional(nullopt_t) noexcept
  459. : optional{}
  460. {}
  461. optional(optional const &) = default;
  462. optional(optional &&) = default;
  463. using base_t::base_t;
  464. CPP_template(typename E, typename... Args)( //
  465. requires constructible_from<T, std::initializer_list<E> &, Args...>) //
  466. constexpr explicit optional(in_place_t, std::initializer_list<E> il,
  467. Args &&... args) //
  468. noexcept(std::is_nothrow_constructible<T, std::initializer_list<E> &,
  469. Args...>::value)
  470. : base_t(in_place, il, static_cast<Args &&>(args)...)
  471. {}
  472. template<typename U = T>
  473. constexpr CPP_ctor(optional)(U && v)( //
  474. requires(!defer::same_as<detail::decay_t<U>, in_place_t>) &&
  475. (!defer::same_as<detail::decay_t<U>,
  476. optional>)&&defer::constructible_from<T, U> &&
  477. defer::convertible_to<U, T>)
  478. : base_t(in_place, static_cast<U &&>(v))
  479. {}
  480. template<typename U = T>
  481. explicit constexpr CPP_ctor(optional)(U && v)( //
  482. requires(!defer::same_as<detail::decay_t<U>, in_place_t>) &&
  483. (!defer::same_as<detail::decay_t<U>,
  484. optional>)&&defer::constructible_from<T, U> &&
  485. (!defer::convertible_to<U, T>))
  486. : base_t(in_place, static_cast<U &&>(v))
  487. {}
  488. template<typename U>
  489. CPP_ctor(optional)(optional<U> const & that)( //
  490. requires optional_should_convert<U, T> && constructible_from<T, U const &> &&
  491. convertible_to<U const &, T>)
  492. {
  493. if(that.has_value())
  494. base_t::construct_from(*that);
  495. }
  496. template<typename U>
  497. explicit CPP_ctor(optional)(optional<U> const & that)( //
  498. requires optional_should_convert<U, T> && constructible_from<T, U const &> &&
  499. (!convertible_to<U const &, T>))
  500. {
  501. if(that.has_value())
  502. base_t::construct_from(*that);
  503. }
  504. template<typename U>
  505. CPP_ctor(optional)(optional<U> && that)( //
  506. requires optional_should_convert<U, T> && constructible_from<T, U> &&
  507. convertible_to<U, T>)
  508. {
  509. if(that.has_value())
  510. base_t::construct_from(detail::move(*that));
  511. }
  512. template<typename U>
  513. explicit CPP_ctor(optional)(optional<U> && that)( //
  514. requires optional_should_convert<U, T> && constructible_from<T, U> &&
  515. (!convertible_to<U, T>))
  516. {
  517. if(that.has_value())
  518. base_t::construct_from(detail::move(*that));
  519. }
  520. constexpr optional & operator=(nullopt_t) noexcept
  521. {
  522. reset();
  523. return *this;
  524. }
  525. optional & operator=(optional const &) = default;
  526. optional & operator=(optional &&) = default;
  527. template<typename U = T>
  528. constexpr auto operator=(U && u) noexcept(
  529. std::is_nothrow_constructible<T, U>::value &&
  530. std::is_nothrow_assignable<T &, U>::value) -> CPP_ret(optional &)( //
  531. requires(!defer::same_as<optional, detail::decay_t<U>>) &&
  532. (!(defer::satisfies<T, std::is_scalar> &&
  533. defer::same_as<T, detail::decay_t<U>>)) &&
  534. defer::constructible_from<T, U> && defer::assignable_from<T &, U>)
  535. {
  536. if(has_value())
  537. **this = static_cast<U &&>(u);
  538. else
  539. base_t::construct_from(static_cast<U &&>(u));
  540. return *this;
  541. }
  542. template<typename U>
  543. constexpr auto operator=(optional<U> const & that) -> CPP_ret(optional &)( //
  544. requires optional_should_convert_assign<U, T> &&
  545. constructible_from<T, const U &> && assignable_from<T &, const U &>)
  546. {
  547. base_t::assign_from(that);
  548. return *this;
  549. }
  550. template<typename U>
  551. constexpr auto operator=(optional<U> && that) -> CPP_ret(optional &)( //
  552. requires optional_should_convert_assign<U, T> && constructible_from<T, U> &&
  553. assignable_from<T &, U>)
  554. {
  555. base_t::assign_from(std::move(that));
  556. return *this;
  557. }
  558. template<typename... Args>
  559. auto emplace(Args &&... args) noexcept(
  560. std::is_nothrow_constructible<T, Args...>::value) -> CPP_ret(T &)( //
  561. requires constructible_from<T, Args...>)
  562. {
  563. reset();
  564. return base_t::construct_from(static_cast<Args &&>(args)...);
  565. }
  566. template<typename E, typename... Args>
  567. auto emplace(std::initializer_list<E> il, Args &&... args) noexcept(
  568. std::is_nothrow_constructible<T, std::initializer_list<E> &, Args...>::value)
  569. -> CPP_ret(T &)( //
  570. requires constructible_from<T, std::initializer_list<E> &, Args &&...>)
  571. {
  572. reset();
  573. return base_t::construct_from(il, static_cast<Args &&>(args)...);
  574. }
  575. using base_t::swap;
  576. using base_t::operator->;
  577. using base_t::operator*;
  578. constexpr explicit operator bool() const noexcept
  579. {
  580. return has_value();
  581. }
  582. using base_t::has_value;
  583. constexpr T const & value() const &
  584. {
  585. return (has_value() || detail::throw_bad_optional_access()), **this;
  586. }
  587. constexpr T & value() &
  588. {
  589. return (has_value() || detail::throw_bad_optional_access()), **this;
  590. }
  591. constexpr T const && value() const &&
  592. {
  593. return (has_value() || detail::throw_bad_optional_access()),
  594. detail::move(**this);
  595. }
  596. constexpr T && value() &&
  597. {
  598. return (has_value() || detail::throw_bad_optional_access()),
  599. detail::move(**this);
  600. }
  601. CPP_template(typename U)( //
  602. requires copy_constructible<T> && convertible_to<U, T>) //
  603. constexpr T value_or(U && u) const &
  604. {
  605. return has_value() ? **this : static_cast<T>((U &&) u);
  606. }
  607. CPP_template(typename U)( //
  608. requires move_constructible<T> && convertible_to<U, T>) //
  609. constexpr T value_or(U && u) &&
  610. {
  611. return has_value() ? detail::move(**this) : static_cast<T>((U &&) u);
  612. }
  613. using base_t::reset;
  614. };
  615. /// \cond
  616. namespace detail
  617. {
  618. namespace optional_adl
  619. {
  620. constexpr bool convert_bool(bool b) noexcept
  621. {
  622. return b;
  623. }
  624. // Relational operators [optional.relops]
  625. template<typename T, typename U>
  626. constexpr auto operator==(optional<T> const & x, optional<U> const & y) //
  627. noexcept(noexcept(convert_bool(*x == *y)))
  628. -> decltype(convert_bool(*x == *y))
  629. {
  630. return x.has_value() == y.has_value() && (!x || convert_bool(*x == *y));
  631. }
  632. template<typename T, typename U>
  633. constexpr auto operator!=(optional<T> const & x, optional<U> const & y) //
  634. noexcept(noexcept(convert_bool(*x != *y)))
  635. -> decltype(convert_bool(*x != *y))
  636. {
  637. return x.has_value() != y.has_value() || (x && convert_bool(*x != *y));
  638. }
  639. template<typename T, typename U>
  640. constexpr auto operator<(optional<T> const & x, optional<U> const & y) //
  641. noexcept(noexcept(convert_bool(*x < *y)))
  642. -> decltype(convert_bool(*x < *y))
  643. {
  644. return y && (!x || convert_bool(*x < *y));
  645. }
  646. template<typename T, typename U>
  647. constexpr auto operator>(optional<T> const & x, optional<U> const & y) //
  648. noexcept(noexcept(convert_bool(*x > *y)))
  649. -> decltype(convert_bool(*x > *y))
  650. {
  651. return x && (!y || convert_bool(*x > *y));
  652. }
  653. template<typename T, typename U>
  654. constexpr auto operator<=(optional<T> const & x, optional<U> const & y) //
  655. noexcept(noexcept(convert_bool(*x <= *y)))
  656. -> decltype(convert_bool(*x <= *y))
  657. {
  658. return !x || (y && convert_bool(*x <= *y));
  659. }
  660. template<typename T, typename U>
  661. constexpr auto operator>=(optional<T> const & x, optional<U> const & y) //
  662. noexcept(noexcept(convert_bool(*x >= *y)))
  663. -> decltype(convert_bool(*x >= *y))
  664. {
  665. return !y || (x && convert_bool(*x >= *y));
  666. }
  667. // Comparisons with nullopt [optional.nullops]
  668. template<typename T>
  669. constexpr bool operator==(optional<T> const & x, nullopt_t) noexcept
  670. {
  671. return !x;
  672. }
  673. template<typename T>
  674. constexpr bool operator==(nullopt_t, optional<T> const & x) noexcept
  675. {
  676. return !x;
  677. }
  678. template<typename T>
  679. constexpr bool operator!=(optional<T> const & x, nullopt_t) noexcept
  680. {
  681. return !!x;
  682. }
  683. template<typename T>
  684. constexpr bool operator!=(nullopt_t, optional<T> const & x) noexcept
  685. {
  686. return !!x;
  687. }
  688. template<typename T>
  689. constexpr bool operator<(optional<T> const &, nullopt_t) noexcept
  690. {
  691. return false;
  692. }
  693. template<typename T>
  694. constexpr bool operator<(nullopt_t, optional<T> const & x) noexcept
  695. {
  696. return !!x;
  697. }
  698. template<typename T>
  699. constexpr bool operator>(optional<T> const & x, nullopt_t) noexcept
  700. {
  701. return !!x;
  702. }
  703. template<typename T>
  704. constexpr bool operator>(nullopt_t, optional<T> const &) noexcept
  705. {
  706. return false;
  707. }
  708. template<typename T>
  709. constexpr bool operator<=(optional<T> const & x, nullopt_t) noexcept
  710. {
  711. return !x;
  712. }
  713. template<typename T>
  714. constexpr bool operator<=(nullopt_t, optional<T> const &) noexcept
  715. {
  716. return true;
  717. }
  718. template<typename T>
  719. constexpr bool operator>=(optional<T> const &, nullopt_t) noexcept
  720. {
  721. return true;
  722. }
  723. template<typename T>
  724. constexpr bool operator>=(nullopt_t, optional<T> const & x) noexcept
  725. {
  726. return !x;
  727. }
  728. // Comparisons with T [optional.comp_with_t]
  729. template<typename T, typename U>
  730. constexpr auto operator==(optional<T> const & x, U const & y) //
  731. noexcept(noexcept(convert_bool(*x == y))) //
  732. -> decltype(convert_bool(*x == y))
  733. {
  734. return x && convert_bool(*x == y);
  735. }
  736. template<typename T, typename U>
  737. constexpr auto operator==(T const & x, optional<U> const & y) //
  738. noexcept(noexcept(convert_bool(x == *y))) //
  739. -> decltype(convert_bool(x == *y))
  740. {
  741. return y && convert_bool(x == *y);
  742. }
  743. template<typename T, typename U>
  744. constexpr auto operator!=(optional<T> const & x, U const & y) //
  745. noexcept(noexcept(convert_bool(*x != y))) //
  746. -> decltype(convert_bool(*x != y))
  747. {
  748. return !x || convert_bool(*x != y);
  749. }
  750. template<typename T, typename U>
  751. constexpr auto operator!=(T const & x, optional<U> const & y) //
  752. noexcept(noexcept(convert_bool(x != *y))) //
  753. -> decltype(convert_bool(x != *y))
  754. {
  755. return !y || convert_bool(x != *y);
  756. }
  757. template<typename T, typename U>
  758. constexpr auto operator<(optional<T> const & x, U const & y) //
  759. noexcept(noexcept(convert_bool(*x < y))) //
  760. -> decltype(convert_bool(*x < y))
  761. {
  762. return !x || convert_bool(*x < y);
  763. }
  764. template<typename T, typename U>
  765. constexpr auto operator<(T const & x, optional<U> const & y) //
  766. noexcept(noexcept(convert_bool(x < *y))) //
  767. -> decltype(convert_bool(x < *y))
  768. {
  769. return y && convert_bool(x < *y);
  770. }
  771. template<typename T, typename U>
  772. constexpr auto operator>(optional<T> const & x, U const & y) //
  773. noexcept(noexcept(convert_bool(*x > y))) -> decltype(convert_bool(*x > y))
  774. {
  775. return x && convert_bool(*x > y);
  776. }
  777. template<typename T, typename U>
  778. constexpr auto operator>(T const & x, optional<U> const & y) //
  779. noexcept(noexcept(convert_bool(x > *y))) //
  780. -> decltype(convert_bool(x > *y))
  781. {
  782. return !y || convert_bool(x > *y);
  783. }
  784. template<typename T, typename U>
  785. constexpr auto operator<=(optional<T> const & x, U const & y) //
  786. noexcept(noexcept(convert_bool(*x <= y))) //
  787. -> decltype(convert_bool(*x <= y))
  788. {
  789. return !x || convert_bool(*x <= y);
  790. }
  791. template<typename T, typename U>
  792. constexpr auto operator<=(T const & x, optional<U> const & y) //
  793. noexcept(noexcept(convert_bool(x <= *y))) //
  794. -> decltype(convert_bool(x <= *y))
  795. {
  796. return y && convert_bool(x <= *y);
  797. }
  798. template<typename T, typename U>
  799. constexpr auto operator>=(optional<T> const & x, U const & y) //
  800. noexcept(noexcept(convert_bool(*x >= y))) //
  801. -> decltype(convert_bool(*x >= y))
  802. {
  803. return x && convert_bool(*x >= y);
  804. }
  805. template<typename T, typename U>
  806. constexpr auto operator>=(T const & x, optional<U> const & y) //
  807. noexcept(noexcept(convert_bool(x >= *y))) //
  808. -> decltype(convert_bool(x >= *y))
  809. {
  810. return !y || convert_bool(x >= *y);
  811. }
  812. // clang-format off
  813. template<typename T>
  814. auto CPP_auto_fun(swap)(optional<T> &x, optional<T> &y)
  815. (
  816. return x.swap(y)
  817. )
  818. // clang-format on
  819. } // namespace optional_adl
  820. } // namespace detail
  821. /// \endcond
  822. // clang-format off
  823. template<typename T>
  824. constexpr auto CPP_auto_fun(make_optional)(T &&t)
  825. (
  826. return optional<detail::decay_t<T>>{static_cast<T &&>(t)}
  827. )
  828. template<typename T, typename... Args>
  829. constexpr auto CPP_auto_fun(make_optional)(Args &&... args)
  830. (
  831. return optional<T>{in_place, static_cast<Args &&>(args)...}
  832. )
  833. template<typename T, typename U, typename... Args>
  834. constexpr auto CPP_auto_fun(make_optional)(std::initializer_list<U> il,
  835. Args &&... args)
  836. (
  837. return optional<T>{in_place, il, static_cast<Args &&>(args)...}
  838. )
  839. // clang-format on
  840. /// \cond
  841. namespace detail
  842. {
  843. template<typename T, typename Tag = void, bool Enable = true>
  844. struct non_propagating_cache : optional<T>
  845. {
  846. non_propagating_cache() = default;
  847. constexpr non_propagating_cache(nullopt_t) noexcept
  848. {}
  849. constexpr non_propagating_cache(non_propagating_cache const &) noexcept
  850. : optional<T>{}
  851. {}
  852. constexpr non_propagating_cache(non_propagating_cache && that) noexcept
  853. : optional<T>{}
  854. {
  855. that.optional<T>::reset();
  856. }
  857. constexpr non_propagating_cache & operator=(
  858. non_propagating_cache const &) noexcept
  859. {
  860. optional<T>::reset();
  861. return *this;
  862. }
  863. constexpr non_propagating_cache & operator=(
  864. non_propagating_cache && that) noexcept
  865. {
  866. that.optional<T>::reset();
  867. optional<T>::reset();
  868. return *this;
  869. }
  870. using optional<T>::operator=;
  871. };
  872. template<typename T, typename Tag>
  873. struct non_propagating_cache<T, Tag, false>
  874. {};
  875. } // namespace detail
  876. /// \endcond
  877. } // namespace ranges
  878. #endif