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.

944 lines
26KB

  1. // <optional> -*- C++ -*-
  2. // Copyright (C) 2013-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file experimental/optional
  21. * This is a TS C++ Library header.
  22. * @ingroup libfund-ts
  23. */
  24. #ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
  25. #define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
  26. #if __cplusplus >= 201402L
  27. #include <utility>
  28. #include <type_traits>
  29. #include <stdexcept>
  30. #include <new>
  31. #include <initializer_list>
  32. #include <bits/functexcept.h>
  33. #include <bits/functional_hash.h>
  34. #include <bits/enable_special_members.h>
  35. #include <experimental/bits/lfts_config.h>
  36. namespace std _GLIBCXX_VISIBILITY(default)
  37. {
  38. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  39. namespace experimental
  40. {
  41. inline namespace fundamentals_v1
  42. {
  43. /**
  44. * @defgroup optional Optional values
  45. * @ingroup libfund-ts
  46. *
  47. * Class template for optional values and surrounding facilities, as
  48. * described in n3793 "A proposal to add a utility class to represent
  49. * optional objects (Revision 5)".
  50. *
  51. * @{
  52. */
  53. #define __cpp_lib_experimental_optional 201411
  54. // All subsequent [X.Y.n] references are against n3793.
  55. // [X.Y.4]
  56. template<typename _Tp>
  57. class optional;
  58. // [X.Y.5]
  59. /// Tag type for in-place construction.
  60. struct in_place_t { };
  61. /// Tag for in-place construction.
  62. constexpr in_place_t in_place { };
  63. // [X.Y.6]
  64. /// Tag type to disengage optional objects.
  65. struct nullopt_t
  66. {
  67. // Do not user-declare default constructor at all for
  68. // optional_value = {} syntax to work.
  69. // nullopt_t() = delete;
  70. // Used for constructing nullopt.
  71. enum class _Construct { _Token };
  72. // Must be constexpr for nullopt_t to be literal.
  73. explicit constexpr nullopt_t(_Construct) { }
  74. };
  75. // [X.Y.6]
  76. /// Tag to disengage optional objects.
  77. constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
  78. // [X.Y.7]
  79. /**
  80. * @brief Exception class thrown when a disengaged optional object is
  81. * dereferenced.
  82. * @ingroup exceptions
  83. */
  84. class bad_optional_access : public logic_error
  85. {
  86. public:
  87. bad_optional_access() : logic_error("bad optional access") { }
  88. // XXX This constructor is non-standard. Should not be inline
  89. explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
  90. virtual ~bad_optional_access() noexcept = default;
  91. };
  92. /// @cond undocumented
  93. void
  94. __throw_bad_optional_access(const char*)
  95. __attribute__((__noreturn__));
  96. // XXX Does not belong here.
  97. inline void
  98. __throw_bad_optional_access(const char* __s)
  99. { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
  100. /**
  101. * @brief Class template that holds the necessary state for @ref optional
  102. * and that has the responsibility for construction and the special members.
  103. *
  104. * Such a separate base class template is necessary in order to
  105. * conditionally enable the special members (e.g. copy/move constructors).
  106. * Note that this means that @ref _Optional_base implements the
  107. * functionality for copy and move assignment, but not for converting
  108. * assignment.
  109. *
  110. * @see optional, _Enable_special_members
  111. */
  112. template<typename _Tp, bool _ShouldProvideDestructor =
  113. !is_trivially_destructible<_Tp>::value>
  114. class _Optional_base
  115. {
  116. private:
  117. // Remove const to avoid prohibition of reusing object storage for
  118. // const-qualified types in [3.8/9]. This is strictly internal
  119. // and even optional itself is oblivious to it.
  120. using _Stored_type = remove_const_t<_Tp>;
  121. public:
  122. // [X.Y.4.1] Constructors.
  123. // Constructors for disengaged optionals.
  124. constexpr _Optional_base() noexcept
  125. : _M_empty{} { }
  126. constexpr _Optional_base(nullopt_t) noexcept
  127. : _Optional_base{} { }
  128. // Constructors for engaged optionals.
  129. template<typename... _Args>
  130. constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
  131. : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
  132. template<typename _Up, typename... _Args,
  133. enable_if_t<is_constructible<_Tp,
  134. initializer_list<_Up>&,
  135. _Args&&...>::value,
  136. int>...>
  137. constexpr explicit _Optional_base(in_place_t,
  138. initializer_list<_Up> __il,
  139. _Args&&... __args)
  140. : _M_payload(__il, std::forward<_Args>(__args)...),
  141. _M_engaged(true) { }
  142. // Copy and move constructors.
  143. _Optional_base(const _Optional_base& __other)
  144. {
  145. if (__other._M_engaged)
  146. this->_M_construct(__other._M_get());
  147. }
  148. _Optional_base(_Optional_base&& __other)
  149. noexcept(is_nothrow_move_constructible<_Tp>())
  150. {
  151. if (__other._M_engaged)
  152. this->_M_construct(std::move(__other._M_get()));
  153. }
  154. // [X.Y.4.3] (partly) Assignment.
  155. _Optional_base&
  156. operator=(const _Optional_base& __other)
  157. {
  158. if (this->_M_engaged && __other._M_engaged)
  159. this->_M_get() = __other._M_get();
  160. else
  161. {
  162. if (__other._M_engaged)
  163. this->_M_construct(__other._M_get());
  164. else
  165. this->_M_reset();
  166. }
  167. return *this;
  168. }
  169. _Optional_base&
  170. operator=(_Optional_base&& __other)
  171. noexcept(__and_<is_nothrow_move_constructible<_Tp>,
  172. is_nothrow_move_assignable<_Tp>>())
  173. {
  174. if (this->_M_engaged && __other._M_engaged)
  175. this->_M_get() = std::move(__other._M_get());
  176. else
  177. {
  178. if (__other._M_engaged)
  179. this->_M_construct(std::move(__other._M_get()));
  180. else
  181. this->_M_reset();
  182. }
  183. return *this;
  184. }
  185. // [X.Y.4.2] Destructor.
  186. ~_Optional_base()
  187. {
  188. if (this->_M_engaged)
  189. this->_M_payload.~_Stored_type();
  190. }
  191. // The following functionality is also needed by optional, hence the
  192. // protected accessibility.
  193. protected:
  194. constexpr bool _M_is_engaged() const noexcept
  195. { return this->_M_engaged; }
  196. // The _M_get operations have _M_engaged as a precondition.
  197. constexpr _Tp&
  198. _M_get() noexcept
  199. { return _M_payload; }
  200. constexpr const _Tp&
  201. _M_get() const noexcept
  202. { return _M_payload; }
  203. // The _M_construct operation has !_M_engaged as a precondition
  204. // while _M_destruct has _M_engaged as a precondition.
  205. template<typename... _Args>
  206. void
  207. _M_construct(_Args&&... __args)
  208. noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
  209. {
  210. ::new (std::__addressof(this->_M_payload))
  211. _Stored_type(std::forward<_Args>(__args)...);
  212. this->_M_engaged = true;
  213. }
  214. void
  215. _M_destruct()
  216. {
  217. this->_M_engaged = false;
  218. this->_M_payload.~_Stored_type();
  219. }
  220. // _M_reset is a 'safe' operation with no precondition.
  221. void
  222. _M_reset()
  223. {
  224. if (this->_M_engaged)
  225. this->_M_destruct();
  226. }
  227. private:
  228. struct _Empty_byte { };
  229. union {
  230. _Empty_byte _M_empty;
  231. _Stored_type _M_payload;
  232. };
  233. bool _M_engaged = false;
  234. };
  235. /// Partial specialization that is exactly identical to the primary template
  236. /// save for not providing a destructor, to fulfill triviality requirements.
  237. template<typename _Tp>
  238. class _Optional_base<_Tp, false>
  239. {
  240. private:
  241. using _Stored_type = remove_const_t<_Tp>;
  242. public:
  243. constexpr _Optional_base() noexcept
  244. : _M_empty{} { }
  245. constexpr _Optional_base(nullopt_t) noexcept
  246. : _Optional_base{} { }
  247. template<typename... _Args>
  248. constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
  249. : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
  250. template<typename _Up, typename... _Args,
  251. enable_if_t<is_constructible<_Tp,
  252. initializer_list<_Up>&,
  253. _Args&&...>::value,
  254. int>...>
  255. constexpr explicit _Optional_base(in_place_t,
  256. initializer_list<_Up> __il,
  257. _Args&&... __args)
  258. : _M_payload(__il, std::forward<_Args>(__args)...),
  259. _M_engaged(true) { }
  260. _Optional_base(const _Optional_base& __other)
  261. {
  262. if (__other._M_engaged)
  263. this->_M_construct(__other._M_get());
  264. }
  265. _Optional_base(_Optional_base&& __other)
  266. noexcept(is_nothrow_move_constructible<_Tp>())
  267. {
  268. if (__other._M_engaged)
  269. this->_M_construct(std::move(__other._M_get()));
  270. }
  271. _Optional_base&
  272. operator=(const _Optional_base& __other)
  273. {
  274. if (this->_M_engaged && __other._M_engaged)
  275. this->_M_get() = __other._M_get();
  276. else
  277. {
  278. if (__other._M_engaged)
  279. this->_M_construct(__other._M_get());
  280. else
  281. this->_M_reset();
  282. }
  283. return *this;
  284. }
  285. _Optional_base&
  286. operator=(_Optional_base&& __other)
  287. noexcept(__and_<is_nothrow_move_constructible<_Tp>,
  288. is_nothrow_move_assignable<_Tp>>())
  289. {
  290. if (this->_M_engaged && __other._M_engaged)
  291. this->_M_get() = std::move(__other._M_get());
  292. else
  293. {
  294. if (__other._M_engaged)
  295. this->_M_construct(std::move(__other._M_get()));
  296. else
  297. this->_M_reset();
  298. }
  299. return *this;
  300. }
  301. // Sole difference
  302. // ~_Optional_base() noexcept = default;
  303. protected:
  304. constexpr bool _M_is_engaged() const noexcept
  305. { return this->_M_engaged; }
  306. _Tp&
  307. _M_get() noexcept
  308. { return _M_payload; }
  309. constexpr const _Tp&
  310. _M_get() const noexcept
  311. { return _M_payload; }
  312. template<typename... _Args>
  313. void
  314. _M_construct(_Args&&... __args)
  315. noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
  316. {
  317. ::new (std::__addressof(this->_M_payload))
  318. _Stored_type(std::forward<_Args>(__args)...);
  319. this->_M_engaged = true;
  320. }
  321. void
  322. _M_destruct()
  323. {
  324. this->_M_engaged = false;
  325. this->_M_payload.~_Stored_type();
  326. }
  327. void
  328. _M_reset()
  329. {
  330. if (this->_M_engaged)
  331. this->_M_destruct();
  332. }
  333. private:
  334. struct _Empty_byte { };
  335. union
  336. {
  337. _Empty_byte _M_empty;
  338. _Stored_type _M_payload;
  339. };
  340. bool _M_engaged = false;
  341. };
  342. template<typename _Tp, typename _Up>
  343. using __converts_from_optional =
  344. __or_<is_constructible<_Tp, const optional<_Up>&>,
  345. is_constructible<_Tp, optional<_Up>&>,
  346. is_constructible<_Tp, const optional<_Up>&&>,
  347. is_constructible<_Tp, optional<_Up>&&>,
  348. is_convertible<const optional<_Up>&, _Tp>,
  349. is_convertible<optional<_Up>&, _Tp>,
  350. is_convertible<const optional<_Up>&&, _Tp>,
  351. is_convertible<optional<_Up>&&, _Tp>>;
  352. template<typename _Tp, typename _Up>
  353. using __assigns_from_optional =
  354. __or_<is_assignable<_Tp&, const optional<_Up>&>,
  355. is_assignable<_Tp&, optional<_Up>&>,
  356. is_assignable<_Tp&, const optional<_Up>&&>,
  357. is_assignable<_Tp&, optional<_Up>&&>>;
  358. /// @endcond
  359. /**
  360. * @brief Class template for optional values.
  361. */
  362. template<typename _Tp>
  363. class optional
  364. : private _Optional_base<_Tp>,
  365. private _Enable_copy_move<
  366. // Copy constructor.
  367. is_copy_constructible<_Tp>::value,
  368. // Copy assignment.
  369. __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
  370. // Move constructor.
  371. is_move_constructible<_Tp>::value,
  372. // Move assignment.
  373. __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
  374. // Unique tag type.
  375. optional<_Tp>>
  376. {
  377. static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>,
  378. __not_<is_same<remove_cv_t<_Tp>, in_place_t>>,
  379. __not_<is_reference<_Tp>>>(),
  380. "Invalid instantiation of optional<T>");
  381. private:
  382. using _Base = _Optional_base<_Tp>;
  383. public:
  384. using value_type = _Tp;
  385. // _Optional_base has the responsibility for construction.
  386. using _Base::_Base;
  387. constexpr optional() = default;
  388. // Converting constructors for engaged optionals.
  389. template <typename _Up = _Tp,
  390. enable_if_t<__and_<
  391. __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
  392. is_constructible<_Tp, _Up&&>,
  393. is_convertible<_Up&&, _Tp>
  394. >::value, bool> = true>
  395. constexpr optional(_Up&& __t)
  396. : _Base(in_place, std::forward<_Up>(__t)) { }
  397. template <typename _Up = _Tp,
  398. enable_if_t<__and_<
  399. __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
  400. is_constructible<_Tp, _Up&&>,
  401. __not_<is_convertible<_Up&&, _Tp>>
  402. >::value, bool> = false>
  403. explicit constexpr optional(_Up&& __t)
  404. : _Base(in_place, std::forward<_Up>(__t)) { }
  405. template <typename _Up,
  406. enable_if_t<__and_<
  407. __not_<is_same<_Tp, _Up>>,
  408. is_constructible<_Tp, const _Up&>,
  409. is_convertible<const _Up&, _Tp>,
  410. __not_<__converts_from_optional<_Tp, _Up>>
  411. >::value, bool> = true>
  412. constexpr optional(const optional<_Up>& __t)
  413. {
  414. if (__t)
  415. emplace(*__t);
  416. }
  417. template <typename _Up,
  418. enable_if_t<__and_<
  419. __not_<is_same<_Tp, _Up>>,
  420. is_constructible<_Tp, const _Up&>,
  421. __not_<is_convertible<const _Up&, _Tp>>,
  422. __not_<__converts_from_optional<_Tp, _Up>>
  423. >::value, bool> = false>
  424. explicit constexpr optional(const optional<_Up>& __t)
  425. {
  426. if (__t)
  427. emplace(*__t);
  428. }
  429. template <typename _Up,
  430. enable_if_t<__and_<
  431. __not_<is_same<_Tp, _Up>>,
  432. is_constructible<_Tp, _Up&&>,
  433. is_convertible<_Up&&, _Tp>,
  434. __not_<__converts_from_optional<_Tp, _Up>>
  435. >::value, bool> = true>
  436. constexpr optional(optional<_Up>&& __t)
  437. {
  438. if (__t)
  439. emplace(std::move(*__t));
  440. }
  441. template <typename _Up,
  442. enable_if_t<__and_<
  443. __not_<is_same<_Tp, _Up>>,
  444. is_constructible<_Tp, _Up&&>,
  445. __not_<is_convertible<_Up&&, _Tp>>,
  446. __not_<__converts_from_optional<_Tp, _Up>>
  447. >::value, bool> = false>
  448. explicit constexpr optional(optional<_Up>&& __t)
  449. {
  450. if (__t)
  451. emplace(std::move(*__t));
  452. }
  453. // [X.Y.4.3] (partly) Assignment.
  454. optional&
  455. operator=(nullopt_t) noexcept
  456. {
  457. this->_M_reset();
  458. return *this;
  459. }
  460. template<typename _Up = _Tp>
  461. enable_if_t<__and_<
  462. __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
  463. is_constructible<_Tp, _Up>,
  464. __not_<__and_<is_scalar<_Tp>,
  465. is_same<_Tp, decay_t<_Up>>>>,
  466. is_assignable<_Tp&, _Up>>::value,
  467. optional&>
  468. operator=(_Up&& __u)
  469. {
  470. if (this->_M_is_engaged())
  471. this->_M_get() = std::forward<_Up>(__u);
  472. else
  473. this->_M_construct(std::forward<_Up>(__u));
  474. return *this;
  475. }
  476. template<typename _Up>
  477. enable_if_t<__and_<
  478. __not_<is_same<_Tp, _Up>>,
  479. is_constructible<_Tp, const _Up&>,
  480. is_assignable<_Tp&, _Up>,
  481. __not_<__converts_from_optional<_Tp, _Up>>,
  482. __not_<__assigns_from_optional<_Tp, _Up>>
  483. >::value,
  484. optional&>
  485. operator=(const optional<_Up>& __u)
  486. {
  487. if (__u)
  488. {
  489. if (this->_M_is_engaged())
  490. this->_M_get() = *__u;
  491. else
  492. this->_M_construct(*__u);
  493. }
  494. else
  495. {
  496. this->_M_reset();
  497. }
  498. return *this;
  499. }
  500. template<typename _Up>
  501. enable_if_t<__and_<
  502. __not_<is_same<_Tp, _Up>>,
  503. is_constructible<_Tp, _Up>,
  504. is_assignable<_Tp&, _Up>,
  505. __not_<__converts_from_optional<_Tp, _Up>>,
  506. __not_<__assigns_from_optional<_Tp, _Up>>
  507. >::value,
  508. optional&>
  509. operator=(optional<_Up>&& __u)
  510. {
  511. if (__u)
  512. {
  513. if (this->_M_is_engaged())
  514. this->_M_get() = std::move(*__u);
  515. else
  516. this->_M_construct(std::move(*__u));
  517. }
  518. else
  519. {
  520. this->_M_reset();
  521. }
  522. return *this;
  523. }
  524. template<typename... _Args>
  525. enable_if_t<is_constructible<_Tp, _Args&&...>::value>
  526. emplace(_Args&&... __args)
  527. {
  528. this->_M_reset();
  529. this->_M_construct(std::forward<_Args>(__args)...);
  530. }
  531. template<typename _Up, typename... _Args>
  532. enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
  533. _Args&&...>::value>
  534. emplace(initializer_list<_Up> __il, _Args&&... __args)
  535. {
  536. this->_M_reset();
  537. this->_M_construct(__il, std::forward<_Args>(__args)...);
  538. }
  539. // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base.
  540. // [X.Y.4.4] Swap.
  541. void
  542. swap(optional& __other)
  543. noexcept(is_nothrow_move_constructible<_Tp>()
  544. && __is_nothrow_swappable<_Tp>::value)
  545. {
  546. using std::swap;
  547. if (this->_M_is_engaged() && __other._M_is_engaged())
  548. swap(this->_M_get(), __other._M_get());
  549. else if (this->_M_is_engaged())
  550. {
  551. __other._M_construct(std::move(this->_M_get()));
  552. this->_M_destruct();
  553. }
  554. else if (__other._M_is_engaged())
  555. {
  556. this->_M_construct(std::move(__other._M_get()));
  557. __other._M_destruct();
  558. }
  559. }
  560. // [X.Y.4.5] Observers.
  561. constexpr const _Tp*
  562. operator->() const
  563. { return std::__addressof(this->_M_get()); }
  564. _Tp*
  565. operator->()
  566. { return std::__addressof(this->_M_get()); }
  567. constexpr const _Tp&
  568. operator*() const&
  569. { return this->_M_get(); }
  570. constexpr _Tp&
  571. operator*()&
  572. { return this->_M_get(); }
  573. constexpr _Tp&&
  574. operator*()&&
  575. { return std::move(this->_M_get()); }
  576. constexpr const _Tp&&
  577. operator*() const&&
  578. { return std::move(this->_M_get()); }
  579. constexpr explicit operator bool() const noexcept
  580. { return this->_M_is_engaged(); }
  581. constexpr const _Tp&
  582. value() const&
  583. {
  584. return this->_M_is_engaged()
  585. ? this->_M_get()
  586. : (__throw_bad_optional_access("Attempt to access value of a "
  587. "disengaged optional object"),
  588. this->_M_get());
  589. }
  590. constexpr _Tp&
  591. value()&
  592. {
  593. return this->_M_is_engaged()
  594. ? this->_M_get()
  595. : (__throw_bad_optional_access("Attempt to access value of a "
  596. "disengaged optional object"),
  597. this->_M_get());
  598. }
  599. constexpr _Tp&&
  600. value()&&
  601. {
  602. return this->_M_is_engaged()
  603. ? std::move(this->_M_get())
  604. : (__throw_bad_optional_access("Attempt to access value of a "
  605. "disengaged optional object"),
  606. std::move(this->_M_get()));
  607. }
  608. constexpr const _Tp&&
  609. value() const&&
  610. {
  611. return this->_M_is_engaged()
  612. ? std::move(this->_M_get())
  613. : (__throw_bad_optional_access("Attempt to access value of a "
  614. "disengaged optional object"),
  615. std::move(this->_M_get()));
  616. }
  617. template<typename _Up>
  618. constexpr _Tp
  619. value_or(_Up&& __u) const&
  620. {
  621. static_assert(__and_<is_copy_constructible<_Tp>,
  622. is_convertible<_Up&&, _Tp>>(),
  623. "Cannot return value");
  624. return this->_M_is_engaged()
  625. ? this->_M_get()
  626. : static_cast<_Tp>(std::forward<_Up>(__u));
  627. }
  628. template<typename _Up>
  629. _Tp
  630. value_or(_Up&& __u) &&
  631. {
  632. static_assert(__and_<is_move_constructible<_Tp>,
  633. is_convertible<_Up&&, _Tp>>(),
  634. "Cannot return value" );
  635. return this->_M_is_engaged()
  636. ? std::move(this->_M_get())
  637. : static_cast<_Tp>(std::forward<_Up>(__u));
  638. }
  639. };
  640. /// @relates experimental::optional @{
  641. // [X.Y.8] Comparisons between optional values.
  642. template<typename _Tp>
  643. constexpr bool
  644. operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
  645. {
  646. return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
  647. && (!__lhs || *__lhs == *__rhs);
  648. }
  649. template<typename _Tp>
  650. constexpr bool
  651. operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
  652. { return !(__lhs == __rhs); }
  653. template<typename _Tp>
  654. constexpr bool
  655. operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
  656. {
  657. return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
  658. }
  659. template<typename _Tp>
  660. constexpr bool
  661. operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
  662. { return __rhs < __lhs; }
  663. template<typename _Tp>
  664. constexpr bool
  665. operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
  666. { return !(__rhs < __lhs); }
  667. template<typename _Tp>
  668. constexpr bool
  669. operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
  670. { return !(__lhs < __rhs); }
  671. // [X.Y.9] Comparisons with nullopt.
  672. template<typename _Tp>
  673. constexpr bool
  674. operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
  675. { return !__lhs; }
  676. template<typename _Tp>
  677. constexpr bool
  678. operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
  679. { return !__rhs; }
  680. template<typename _Tp>
  681. constexpr bool
  682. operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
  683. { return static_cast<bool>(__lhs); }
  684. template<typename _Tp>
  685. constexpr bool
  686. operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
  687. { return static_cast<bool>(__rhs); }
  688. template<typename _Tp>
  689. constexpr bool
  690. operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
  691. { return false; }
  692. template<typename _Tp>
  693. constexpr bool
  694. operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
  695. { return static_cast<bool>(__rhs); }
  696. template<typename _Tp>
  697. constexpr bool
  698. operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
  699. { return static_cast<bool>(__lhs); }
  700. template<typename _Tp>
  701. constexpr bool
  702. operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
  703. { return false; }
  704. template<typename _Tp>
  705. constexpr bool
  706. operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
  707. { return !__lhs; }
  708. template<typename _Tp>
  709. constexpr bool
  710. operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
  711. { return true; }
  712. template<typename _Tp>
  713. constexpr bool
  714. operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
  715. { return true; }
  716. template<typename _Tp>
  717. constexpr bool
  718. operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
  719. { return !__rhs; }
  720. // [X.Y.10] Comparisons with value type.
  721. template<typename _Tp>
  722. constexpr bool
  723. operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
  724. { return __lhs && *__lhs == __rhs; }
  725. template<typename _Tp>
  726. constexpr bool
  727. operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
  728. { return __rhs && __lhs == *__rhs; }
  729. template<typename _Tp>
  730. constexpr bool
  731. operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs)
  732. { return !__lhs || !(*__lhs == __rhs); }
  733. template<typename _Tp>
  734. constexpr bool
  735. operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
  736. { return !__rhs || !(__lhs == *__rhs); }
  737. template<typename _Tp>
  738. constexpr bool
  739. operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
  740. { return !__lhs || *__lhs < __rhs; }
  741. template<typename _Tp>
  742. constexpr bool
  743. operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
  744. { return __rhs && __lhs < *__rhs; }
  745. template<typename _Tp>
  746. constexpr bool
  747. operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
  748. { return __lhs && __rhs < *__lhs; }
  749. template<typename _Tp>
  750. constexpr bool
  751. operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
  752. { return !__rhs || *__rhs < __lhs; }
  753. template<typename _Tp>
  754. constexpr bool
  755. operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
  756. { return !__lhs || !(__rhs < *__lhs); }
  757. template<typename _Tp>
  758. constexpr bool
  759. operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
  760. { return __rhs && !(*__rhs < __lhs); }
  761. template<typename _Tp>
  762. constexpr bool
  763. operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
  764. { return __lhs && !(*__lhs < __rhs); }
  765. template<typename _Tp>
  766. constexpr bool
  767. operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
  768. { return !__rhs || !(__lhs < *__rhs); }
  769. // [X.Y.11]
  770. template<typename _Tp>
  771. inline void
  772. swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
  773. noexcept(noexcept(__lhs.swap(__rhs)))
  774. { __lhs.swap(__rhs); }
  775. template<typename _Tp>
  776. constexpr optional<decay_t<_Tp>>
  777. make_optional(_Tp&& __t)
  778. { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
  779. // @} relates experimental::optional
  780. // @} group optional
  781. } // namespace fundamentals_v1
  782. } // namespace experimental
  783. // [X.Y.12]
  784. /// std::hash partial specialization for experimental::optional
  785. /// @relates experimental::optional
  786. template<typename _Tp>
  787. struct hash<experimental::optional<_Tp>>
  788. {
  789. using result_type = size_t;
  790. using argument_type = experimental::optional<_Tp>;
  791. size_t
  792. operator()(const experimental::optional<_Tp>& __t) const
  793. noexcept(noexcept(hash<_Tp> {}(*__t)))
  794. {
  795. // We pick an arbitrary hash for disengaged optionals which hopefully
  796. // usual values of _Tp won't typically hash to.
  797. constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
  798. return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
  799. }
  800. };
  801. _GLIBCXX_END_NAMESPACE_VERSION
  802. } // namespace std
  803. #endif // C++14
  804. #endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL