Home | History | Annotate | Line # | Download | only in std
      1 // <optional> -*- C++ -*-
      2 
      3 // Copyright (C) 2013-2022 Free Software Foundation, Inc.
      4 // Copyright The GNU Toolchain Authors.
      5 //
      6 // This file is part of the GNU ISO C++ Library.  This library is free
      7 // software; you can redistribute it and/or modify it under the
      8 // terms of the GNU General Public License as published by the
      9 // Free Software Foundation; either version 3, or (at your option)
     10 // any later version.
     11 
     12 // This library is distributed in the hope that it will be useful,
     13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 // GNU General Public License for more details.
     16 
     17 // Under Section 7 of GPL version 3, you are granted additional
     18 // permissions described in the GCC Runtime Library Exception, version
     19 // 3.1, as published by the Free Software Foundation.
     20 
     21 // You should have received a copy of the GNU General Public License and
     22 // a copy of the GCC Runtime Library Exception along with this program;
     23 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24 // <http://www.gnu.org/licenses/>.
     25 
     26 /** @file include/optional
     27  *  This is a Standard C++ Library header.
     28  */
     29 
     30 #ifndef _GLIBCXX_OPTIONAL
     31 #define _GLIBCXX_OPTIONAL 1
     32 
     33 #pragma GCC system_header
     34 
     35 #if __cplusplus >= 201703L
     36 
     37 #include <type_traits>
     38 #include <exception>
     39 #include <new>
     40 #include <initializer_list>
     41 #include <bits/enable_special_members.h>
     42 #include <bits/exception_defines.h>
     43 #include <bits/functional_hash.h>
     44 #include <bits/stl_construct.h> // _Construct
     45 #include <bits/utility.h> // in_place_t
     46 #if __cplusplus > 201703L
     47 # include <compare>
     48 # include <bits/invoke.h> // std::__invoke
     49 #endif
     50 #if __cplusplus > 202002L
     51 # include <concepts>
     52 #endif
     53 
     54 namespace std _GLIBCXX_VISIBILITY(default)
     55 {
     56 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     57 
     58   /**
     59    *  @addtogroup utilities
     60    *  @{
     61    */
     62 
     63 #if __cplusplus > 202002L && __cpp_lib_concepts
     64 # define __cpp_lib_optional 202110L
     65 #elif __cplusplus >= 202002L
     66 # define __cpp_lib_optional 202106L
     67 #else
     68 # define __cpp_lib_optional 201606L
     69 #endif
     70 
     71   template<typename _Tp>
     72     class optional;
     73 
     74   /// Tag type to disengage optional objects.
     75   struct nullopt_t
     76   {
     77     // Do not user-declare default constructor at all for
     78     // optional_value = {} syntax to work.
     79     // nullopt_t() = delete;
     80 
     81     // Used for constructing nullopt.
     82     enum class _Construct { _Token };
     83 
     84     // Must be constexpr for nullopt_t to be literal.
     85     explicit constexpr nullopt_t(_Construct) noexcept { }
     86   };
     87 
     88   /// Tag to disengage optional objects.
     89   inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
     90 
     91   template<typename _Fn> struct _Optional_func { _Fn& _M_f; };
     92 
     93   /**
     94    *  @brief Exception class thrown when a disengaged optional object is
     95    *  dereferenced.
     96    *  @ingroup exceptions
     97    */
     98   class bad_optional_access : public exception
     99   {
    100   public:
    101     bad_optional_access() = default;
    102     virtual ~bad_optional_access() = default;
    103 
    104     const char* what() const noexcept override
    105     { return "bad optional access"; }
    106   };
    107 
    108   // XXX Does not belong here.
    109   [[__noreturn__]] inline void
    110   __throw_bad_optional_access()
    111   { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); }
    112 
    113   // This class template manages construction/destruction of
    114   // the contained value for a std::optional.
    115   template <typename _Tp>
    116     struct _Optional_payload_base
    117     {
    118       using _Stored_type = remove_const_t<_Tp>;
    119 
    120       _Optional_payload_base() = default;
    121       ~_Optional_payload_base() = default;
    122 
    123       template<typename... _Args>
    124 	constexpr
    125 	_Optional_payload_base(in_place_t __tag, _Args&&... __args)
    126 	: _M_payload(__tag, std::forward<_Args>(__args)...),
    127 	  _M_engaged(true)
    128 	{ }
    129 
    130       template<typename _Up, typename... _Args>
    131 	constexpr
    132 	_Optional_payload_base(std::initializer_list<_Up> __il,
    133 			       _Args&&... __args)
    134 	: _M_payload(__il, std::forward<_Args>(__args)...),
    135 	  _M_engaged(true)
    136 	{ }
    137 
    138       // Constructor used by _Optional_base copy constructor when the
    139       // contained value is not trivially copy constructible.
    140       constexpr
    141       _Optional_payload_base(bool __engaged,
    142 			     const _Optional_payload_base& __other)
    143       {
    144 	if (__other._M_engaged)
    145 	  this->_M_construct(__other._M_get());
    146       }
    147 
    148       // Constructor used by _Optional_base move constructor when the
    149       // contained value is not trivially move constructible.
    150       constexpr
    151       _Optional_payload_base(bool __engaged,
    152 			     _Optional_payload_base&& __other)
    153       {
    154 	if (__other._M_engaged)
    155 	  this->_M_construct(std::move(__other._M_get()));
    156       }
    157 
    158       // Copy constructor is only used to when the contained value is
    159       // trivially copy constructible.
    160       _Optional_payload_base(const _Optional_payload_base&) = default;
    161 
    162       // Move constructor is only used to when the contained value is
    163       // trivially copy constructible.
    164       _Optional_payload_base(_Optional_payload_base&&) = default;
    165 
    166       _Optional_payload_base&
    167       operator=(const _Optional_payload_base&) = default;
    168 
    169       _Optional_payload_base&
    170       operator=(_Optional_payload_base&&) = default;
    171 
    172       // used to perform non-trivial copy assignment.
    173       constexpr void
    174       _M_copy_assign(const _Optional_payload_base& __other)
    175       {
    176 	if (this->_M_engaged && __other._M_engaged)
    177 	  this->_M_get() = __other._M_get();
    178 	else
    179 	  {
    180 	    if (__other._M_engaged)
    181 	      this->_M_construct(__other._M_get());
    182 	    else
    183 	      this->_M_reset();
    184 	  }
    185       }
    186 
    187       // used to perform non-trivial move assignment.
    188       constexpr void
    189       _M_move_assign(_Optional_payload_base&& __other)
    190       noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
    191 		       is_nothrow_move_assignable<_Tp>>)
    192       {
    193 	if (this->_M_engaged && __other._M_engaged)
    194 	  this->_M_get() = std::move(__other._M_get());
    195 	else
    196 	  {
    197 	    if (__other._M_engaged)
    198 	      this->_M_construct(std::move(__other._M_get()));
    199 	    else
    200 	      this->_M_reset();
    201 	  }
    202       }
    203 
    204       struct _Empty_byte { };
    205 
    206       template<typename _Up, bool = is_trivially_destructible_v<_Up>>
    207 	union _Storage
    208 	{
    209 	  constexpr _Storage() noexcept : _M_empty() { }
    210 
    211 	  template<typename... _Args>
    212 	    constexpr
    213 	    _Storage(in_place_t, _Args&&... __args)
    214 	    : _M_value(std::forward<_Args>(__args)...)
    215 	    { }
    216 
    217 	  template<typename _Vp, typename... _Args>
    218 	    constexpr
    219 	    _Storage(std::initializer_list<_Vp> __il, _Args&&... __args)
    220 	    : _M_value(__il, std::forward<_Args>(__args)...)
    221 	    { }
    222 
    223 #if __cplusplus >= 202002L
    224 	  template<typename _Fn, typename _Arg>
    225 	    constexpr
    226 	    _Storage(_Optional_func<_Fn> __f, _Arg&& __arg)
    227 	    : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f),
    228 				     std::forward<_Arg>(__arg)))
    229 	    { }
    230 #endif
    231 
    232 	  _Empty_byte _M_empty;
    233 	  _Up _M_value;
    234 	};
    235 
    236       template<typename _Up>
    237 	union _Storage<_Up, false>
    238 	{
    239 	  constexpr _Storage() noexcept : _M_empty() { }
    240 
    241 	  template<typename... _Args>
    242 	    constexpr
    243 	    _Storage(in_place_t, _Args&&... __args)
    244 	    : _M_value(std::forward<_Args>(__args)...)
    245 	    { }
    246 
    247 	  template<typename _Vp, typename... _Args>
    248 	    constexpr
    249 	    _Storage(std::initializer_list<_Vp> __il, _Args&&... __args)
    250 	    : _M_value(__il, std::forward<_Args>(__args)...)
    251 	    { }
    252 
    253 #if __cplusplus >= 202002L
    254 	  template<typename _Fn, typename _Arg>
    255 	    constexpr
    256 	    _Storage(_Optional_func<_Fn> __f, _Arg&& __arg)
    257 	    : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f),
    258 				     std::forward<_Arg>(__arg)))
    259 	    { }
    260 #endif
    261 
    262 	  // User-provided destructor is needed when _Up has non-trivial dtor.
    263 	  _GLIBCXX20_CONSTEXPR ~_Storage() { }
    264 
    265 	  _Empty_byte _M_empty;
    266 	  _Up _M_value;
    267 	};
    268 
    269       _Storage<_Stored_type> _M_payload;
    270 
    271       bool _M_engaged = false;
    272 
    273       template<typename... _Args>
    274 	constexpr void
    275 	_M_construct(_Args&&... __args)
    276 	noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
    277 	{
    278 	  std::_Construct(std::__addressof(this->_M_payload._M_value),
    279 			  std::forward<_Args>(__args)...);
    280 	  this->_M_engaged = true;
    281 	}
    282 
    283       constexpr void
    284       _M_destroy() noexcept
    285       {
    286 	_M_engaged = false;
    287 	_M_payload._M_value.~_Stored_type();
    288       }
    289 
    290 #if __cplusplus >= 202002L
    291       template<typename _Fn, typename _Up>
    292 	constexpr void
    293 	_M_apply(_Optional_func<_Fn> __f, _Up&& __x)
    294 	{
    295 	  std::construct_at(std::__addressof(this->_M_payload),
    296 			    __f, std::forward<_Up>(__x));
    297 	  _M_engaged = true;
    298 	}
    299 #endif
    300 
    301       // The _M_get() operations have _M_engaged as a precondition.
    302       // They exist to access the contained value with the appropriate
    303       // const-qualification, because _M_payload has had the const removed.
    304 
    305       constexpr _Tp&
    306       _M_get() noexcept
    307       { return this->_M_payload._M_value; }
    308 
    309       constexpr const _Tp&
    310       _M_get() const noexcept
    311       { return this->_M_payload._M_value; }
    312 
    313       // _M_reset is a 'safe' operation with no precondition.
    314       constexpr void
    315       _M_reset() noexcept
    316       {
    317 	if (this->_M_engaged)
    318 	  _M_destroy();
    319       }
    320     };
    321 
    322   // Class template that manages the payload for optionals.
    323   template <typename _Tp,
    324 	    bool /*_HasTrivialDestructor*/ =
    325 	      is_trivially_destructible_v<_Tp>,
    326 	    bool /*_HasTrivialCopy */ =
    327 	      is_trivially_copy_assignable_v<_Tp>
    328 	      && is_trivially_copy_constructible_v<_Tp>,
    329 	    bool /*_HasTrivialMove */ =
    330 	      is_trivially_move_assignable_v<_Tp>
    331 	      && is_trivially_move_constructible_v<_Tp>>
    332     struct _Optional_payload;
    333 
    334   // Payload for potentially-constexpr optionals (trivial copy/move/destroy).
    335   template <typename _Tp>
    336     struct _Optional_payload<_Tp, true, true, true>
    337     : _Optional_payload_base<_Tp>
    338     {
    339       using _Optional_payload_base<_Tp>::_Optional_payload_base;
    340 
    341       _Optional_payload() = default;
    342     };
    343 
    344   // Payload for optionals with non-trivial copy construction/assignment.
    345   template <typename _Tp>
    346     struct _Optional_payload<_Tp, true, false, true>
    347     : _Optional_payload_base<_Tp>
    348     {
    349       using _Optional_payload_base<_Tp>::_Optional_payload_base;
    350 
    351       _Optional_payload() = default;
    352       ~_Optional_payload() = default;
    353       _Optional_payload(const _Optional_payload&) = default;
    354       _Optional_payload(_Optional_payload&&) = default;
    355       _Optional_payload& operator=(_Optional_payload&&) = default;
    356 
    357       // Non-trivial copy assignment.
    358       constexpr
    359       _Optional_payload&
    360       operator=(const _Optional_payload& __other)
    361       {
    362 	this->_M_copy_assign(__other);
    363 	return *this;
    364       }
    365     };
    366 
    367   // Payload for optionals with non-trivial move construction/assignment.
    368   template <typename _Tp>
    369     struct _Optional_payload<_Tp, true, true, false>
    370     : _Optional_payload_base<_Tp>
    371     {
    372       using _Optional_payload_base<_Tp>::_Optional_payload_base;
    373 
    374       _Optional_payload() = default;
    375       ~_Optional_payload() = default;
    376       _Optional_payload(const _Optional_payload&) = default;
    377       _Optional_payload(_Optional_payload&&) = default;
    378       _Optional_payload& operator=(const _Optional_payload&) = default;
    379 
    380       // Non-trivial move assignment.
    381       constexpr
    382       _Optional_payload&
    383       operator=(_Optional_payload&& __other)
    384       noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
    385 		       is_nothrow_move_assignable<_Tp>>)
    386       {
    387 	this->_M_move_assign(std::move(__other));
    388 	return *this;
    389       }
    390     };
    391 
    392   // Payload for optionals with non-trivial copy and move assignment.
    393   template <typename _Tp>
    394     struct _Optional_payload<_Tp, true, false, false>
    395     : _Optional_payload_base<_Tp>
    396     {
    397       using _Optional_payload_base<_Tp>::_Optional_payload_base;
    398 
    399       _Optional_payload() = default;
    400       ~_Optional_payload() = default;
    401       _Optional_payload(const _Optional_payload&) = default;
    402       _Optional_payload(_Optional_payload&&) = default;
    403 
    404       // Non-trivial copy assignment.
    405       constexpr
    406       _Optional_payload&
    407       operator=(const _Optional_payload& __other)
    408       {
    409 	this->_M_copy_assign(__other);
    410 	return *this;
    411       }
    412 
    413       // Non-trivial move assignment.
    414       constexpr
    415       _Optional_payload&
    416       operator=(_Optional_payload&& __other)
    417       noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
    418 		       is_nothrow_move_assignable<_Tp>>)
    419       {
    420 	this->_M_move_assign(std::move(__other));
    421 	return *this;
    422       }
    423     };
    424 
    425   // Payload for optionals with non-trivial destructors.
    426   template <typename _Tp, bool _Copy, bool _Move>
    427     struct _Optional_payload<_Tp, false, _Copy, _Move>
    428     : _Optional_payload<_Tp, true, false, false>
    429     {
    430       // Base class implements all the constructors and assignment operators:
    431       using _Optional_payload<_Tp, true, false, false>::_Optional_payload;
    432       _Optional_payload() = default;
    433       _Optional_payload(const _Optional_payload&) = default;
    434       _Optional_payload(_Optional_payload&&) = default;
    435       _Optional_payload& operator=(const _Optional_payload&) = default;
    436       _Optional_payload& operator=(_Optional_payload&&) = default;
    437 
    438       // Destructor needs to destroy the contained value:
    439       _GLIBCXX20_CONSTEXPR ~_Optional_payload() { this->_M_reset(); }
    440     };
    441 
    442   // Common base class for _Optional_base<T> to avoid repeating these
    443   // member functions in each specialization.
    444   template<typename _Tp, typename _Dp>
    445     class _Optional_base_impl
    446     {
    447     protected:
    448       using _Stored_type = remove_const_t<_Tp>;
    449 
    450       // The _M_construct operation has !_M_engaged as a precondition
    451       // while _M_destruct has _M_engaged as a precondition.
    452       template<typename... _Args>
    453 	constexpr void
    454 	_M_construct(_Args&&... __args)
    455 	noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
    456 	{
    457 	  static_cast<_Dp*>(this)->_M_payload._M_construct(
    458 	    std::forward<_Args>(__args)...);
    459 	}
    460 
    461       constexpr void
    462       _M_destruct() noexcept
    463       { static_cast<_Dp*>(this)->_M_payload._M_destroy(); }
    464 
    465       // _M_reset is a 'safe' operation with no precondition.
    466       constexpr void
    467       _M_reset() noexcept
    468       { static_cast<_Dp*>(this)->_M_payload._M_reset(); }
    469 
    470       constexpr bool _M_is_engaged() const noexcept
    471       { return static_cast<const _Dp*>(this)->_M_payload._M_engaged; }
    472 
    473       // The _M_get operations have _M_engaged as a precondition.
    474       constexpr _Tp&
    475       _M_get() noexcept
    476       {
    477 	__glibcxx_assert(this->_M_is_engaged());
    478 	return static_cast<_Dp*>(this)->_M_payload._M_get();
    479       }
    480 
    481       constexpr const _Tp&
    482       _M_get() const noexcept
    483       {
    484 	__glibcxx_assert(this->_M_is_engaged());
    485 	return static_cast<const _Dp*>(this)->_M_payload._M_get();
    486       }
    487     };
    488 
    489   /**
    490     * @brief Class template that provides copy/move constructors of optional.
    491     *
    492     * Such a separate base class template is necessary in order to
    493     * conditionally make copy/move constructors trivial.
    494     *
    495     * When the contained value is trivially copy/move constructible,
    496     * the copy/move constructors of _Optional_base will invoke the
    497     * trivial copy/move constructor of _Optional_payload. Otherwise,
    498     * they will invoke _Optional_payload(bool, const _Optional_payload&)
    499     * or _Optional_payload(bool, _Optional_payload&&) to initialize
    500     * the contained value, if copying/moving an engaged optional.
    501     *
    502     * Whether the other special members are trivial is determined by the
    503     * _Optional_payload<_Tp> specialization used for the _M_payload member.
    504     *
    505     * @see optional, _Enable_special_members
    506     */
    507   template<typename _Tp,
    508 	   bool = is_trivially_copy_constructible_v<_Tp>,
    509 	   bool = is_trivially_move_constructible_v<_Tp>>
    510     struct _Optional_base
    511     : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
    512     {
    513       // Constructors for disengaged optionals.
    514       constexpr _Optional_base() = default;
    515 
    516       // Constructors for engaged optionals.
    517       template<typename... _Args,
    518 	       enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
    519 	constexpr explicit
    520 	_Optional_base(in_place_t, _Args&&... __args)
    521 	: _M_payload(in_place, std::forward<_Args>(__args)...)
    522 	{ }
    523 
    524       template<typename _Up, typename... _Args,
    525 	       enable_if_t<is_constructible_v<_Tp,
    526 					      initializer_list<_Up>&,
    527 					      _Args...>, bool> = false>
    528 	constexpr explicit
    529 	_Optional_base(in_place_t,
    530 		       initializer_list<_Up> __il,
    531 		       _Args&&... __args)
    532 	: _M_payload(in_place, __il, std::forward<_Args>(__args)...)
    533 	{ }
    534 
    535       // Copy and move constructors.
    536       constexpr
    537       _Optional_base(const _Optional_base& __other)
    538       : _M_payload(__other._M_payload._M_engaged, __other._M_payload)
    539       { }
    540 
    541       constexpr
    542       _Optional_base(_Optional_base&& __other)
    543       noexcept(is_nothrow_move_constructible_v<_Tp>)
    544       : _M_payload(__other._M_payload._M_engaged,
    545 		   std::move(__other._M_payload))
    546       { }
    547 
    548       // Assignment operators.
    549       _Optional_base& operator=(const _Optional_base&) = default;
    550       _Optional_base& operator=(_Optional_base&&) = default;
    551 
    552       _Optional_payload<_Tp> _M_payload;
    553     };
    554 
    555   template<typename _Tp>
    556     struct _Optional_base<_Tp, false, true>
    557     : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
    558     {
    559       // Constructors for disengaged optionals.
    560       constexpr _Optional_base() = default;
    561 
    562       // Constructors for engaged optionals.
    563       template<typename... _Args,
    564 	       enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
    565 	constexpr explicit
    566 	_Optional_base(in_place_t, _Args&&... __args)
    567 	: _M_payload(in_place, std::forward<_Args>(__args)...)
    568 	{ }
    569 
    570       template<typename _Up, typename... _Args,
    571 	       enable_if_t<is_constructible_v<_Tp,
    572 					      initializer_list<_Up>&,
    573 					      _Args...>, bool> = false>
    574 	constexpr explicit
    575 	_Optional_base(in_place_t,
    576 		       initializer_list<_Up> __il,
    577 		       _Args... __args)
    578 	: _M_payload(in_place, __il, std::forward<_Args>(__args)...)
    579 	{ }
    580 
    581       // Copy and move constructors.
    582       constexpr _Optional_base(const _Optional_base& __other)
    583       : _M_payload(__other._M_payload._M_engaged, __other._M_payload)
    584       { }
    585 
    586       constexpr _Optional_base(_Optional_base&& __other) = default;
    587 
    588       // Assignment operators.
    589       _Optional_base& operator=(const _Optional_base&) = default;
    590       _Optional_base& operator=(_Optional_base&&) = default;
    591 
    592       _Optional_payload<_Tp> _M_payload;
    593     };
    594 
    595   template<typename _Tp>
    596     struct _Optional_base<_Tp, true, false>
    597     : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
    598     {
    599       // Constructors for disengaged optionals.
    600       constexpr _Optional_base() = default;
    601 
    602       // Constructors for engaged optionals.
    603       template<typename... _Args,
    604 	       enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
    605 	constexpr explicit
    606 	_Optional_base(in_place_t, _Args&&... __args)
    607 	: _M_payload(in_place, std::forward<_Args>(__args)...)
    608 	{ }
    609 
    610       template<typename _Up, typename... _Args,
    611 	       enable_if_t<is_constructible_v<_Tp,
    612 					      initializer_list<_Up>&,
    613 					      _Args...>, bool> = false>
    614 	constexpr explicit
    615 	_Optional_base(in_place_t,
    616 		       initializer_list<_Up> __il,
    617 		       _Args&&... __args)
    618 	: _M_payload(in_place, __il, std::forward<_Args>(__args)...)
    619 	{ }
    620 
    621       // Copy and move constructors.
    622       constexpr _Optional_base(const _Optional_base& __other) = default;
    623 
    624       constexpr
    625       _Optional_base(_Optional_base&& __other)
    626       noexcept(is_nothrow_move_constructible_v<_Tp>)
    627       : _M_payload(__other._M_payload._M_engaged,
    628 		   std::move(__other._M_payload))
    629       { }
    630 
    631       // Assignment operators.
    632       _Optional_base& operator=(const _Optional_base&) = default;
    633       _Optional_base& operator=(_Optional_base&&) = default;
    634 
    635       _Optional_payload<_Tp> _M_payload;
    636     };
    637 
    638   template<typename _Tp>
    639     struct _Optional_base<_Tp, true, true>
    640     : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
    641     {
    642       // Constructors for disengaged optionals.
    643       constexpr _Optional_base() = default;
    644 
    645       // Constructors for engaged optionals.
    646       template<typename... _Args,
    647 	       enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false>
    648 	constexpr explicit
    649 	_Optional_base(in_place_t, _Args&&... __args)
    650 	: _M_payload(in_place, std::forward<_Args>(__args)...)
    651 	{ }
    652 
    653       template<typename _Up, typename... _Args,
    654 	       enable_if_t<is_constructible_v<_Tp,
    655 					      initializer_list<_Up>&,
    656 					      _Args...>, bool> = false>
    657 	constexpr explicit
    658 	_Optional_base(in_place_t,
    659 		       initializer_list<_Up> __il,
    660 		       _Args&&... __args)
    661 	: _M_payload(in_place, __il, std::forward<_Args>(__args)...)
    662 	{ }
    663 
    664       // Copy and move constructors.
    665       constexpr _Optional_base(const _Optional_base& __other) = default;
    666       constexpr _Optional_base(_Optional_base&& __other) = default;
    667 
    668       // Assignment operators.
    669       _Optional_base& operator=(const _Optional_base&) = default;
    670       _Optional_base& operator=(_Optional_base&&) = default;
    671 
    672       _Optional_payload<_Tp> _M_payload;
    673     };
    674 
    675   template<typename _Tp>
    676   class optional;
    677 
    678   template<typename _Tp>
    679     inline constexpr bool __is_optional_v = false;
    680   template<typename _Tp>
    681     inline constexpr bool __is_optional_v<optional<_Tp>> = true;
    682 
    683   template<typename _Tp, typename _Up>
    684     using __converts_from_optional =
    685       __or_<is_constructible<_Tp, const optional<_Up>&>,
    686 	    is_constructible<_Tp, optional<_Up>&>,
    687 	    is_constructible<_Tp, const optional<_Up>&&>,
    688 	    is_constructible<_Tp, optional<_Up>&&>,
    689 	    is_convertible<const optional<_Up>&, _Tp>,
    690 	    is_convertible<optional<_Up>&, _Tp>,
    691 	    is_convertible<const optional<_Up>&&, _Tp>,
    692 	    is_convertible<optional<_Up>&&, _Tp>>;
    693 
    694   template<typename _Tp, typename _Up>
    695     using __assigns_from_optional =
    696       __or_<is_assignable<_Tp&, const optional<_Up>&>,
    697 	    is_assignable<_Tp&, optional<_Up>&>,
    698 	    is_assignable<_Tp&, const optional<_Up>&&>,
    699 	    is_assignable<_Tp&, optional<_Up>&&>>;
    700 
    701   /**
    702     * @brief Class template for optional values.
    703     */
    704   template<typename _Tp>
    705     class optional
    706     : private _Optional_base<_Tp>,
    707       private _Enable_copy_move<
    708 	// Copy constructor.
    709 	is_copy_constructible_v<_Tp>,
    710 	// Copy assignment.
    711 	__and_v<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>,
    712 	// Move constructor.
    713 	is_move_constructible_v<_Tp>,
    714 	// Move assignment.
    715 	__and_v<is_move_constructible<_Tp>, is_move_assignable<_Tp>>,
    716 	// Unique tag type.
    717 	optional<_Tp>>
    718     {
    719       static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>);
    720       static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>);
    721       static_assert(!is_reference_v<_Tp>);
    722 
    723     private:
    724       using _Base = _Optional_base<_Tp>;
    725 
    726       // SFINAE helpers
    727       template<typename _Up>
    728 	using __not_self = __not_<is_same<optional, __remove_cvref_t<_Up>>>;
    729       template<typename _Up>
    730 	using __not_tag = __not_<is_same<in_place_t, __remove_cvref_t<_Up>>>;
    731       template<typename... _Cond>
    732 	using _Requires = enable_if_t<__and_v<_Cond...>, bool>;
    733 
    734     public:
    735       using value_type = _Tp;
    736 
    737       constexpr optional() noexcept { }
    738 
    739       constexpr optional(nullopt_t) noexcept { }
    740 
    741       // Converting constructors for engaged optionals.
    742       template<typename _Up = _Tp,
    743 	       _Requires<__not_self<_Up>, __not_tag<_Up>,
    744 			 is_constructible<_Tp, _Up>,
    745 			 is_convertible<_Up, _Tp>> = true>
    746 	constexpr
    747 	optional(_Up&& __t)
    748 	noexcept(is_nothrow_constructible_v<_Tp, _Up>)
    749 	: _Base(std::in_place, std::forward<_Up>(__t)) { }
    750 
    751       template<typename _Up = _Tp,
    752 	       _Requires<__not_self<_Up>, __not_tag<_Up>,
    753 			 is_constructible<_Tp, _Up>,
    754 			 __not_<is_convertible<_Up, _Tp>>> = false>
    755 	explicit constexpr
    756 	optional(_Up&& __t)
    757 	noexcept(is_nothrow_constructible_v<_Tp, _Up>)
    758 	: _Base(std::in_place, std::forward<_Up>(__t)) { }
    759 
    760       template<typename _Up,
    761 	       _Requires<__not_<is_same<_Tp, _Up>>,
    762 			 is_constructible<_Tp, const _Up&>,
    763 			 is_convertible<const _Up&, _Tp>,
    764 			 __not_<__converts_from_optional<_Tp, _Up>>> = true>
    765 	constexpr
    766 	optional(const optional<_Up>& __t)
    767 	noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
    768 	{
    769 	  if (__t)
    770 	    emplace(*__t);
    771 	}
    772 
    773       template<typename _Up,
    774 	       _Requires<__not_<is_same<_Tp, _Up>>,
    775 			 is_constructible<_Tp, const _Up&>,
    776 			 __not_<is_convertible<const _Up&, _Tp>>,
    777 			 __not_<__converts_from_optional<_Tp, _Up>>> = false>
    778 	explicit constexpr
    779 	optional(const optional<_Up>& __t)
    780 	noexcept(is_nothrow_constructible_v<_Tp, const _Up&>)
    781 	{
    782 	  if (__t)
    783 	    emplace(*__t);
    784 	}
    785 
    786       template<typename _Up,
    787 	       _Requires<__not_<is_same<_Tp, _Up>>,
    788 			 is_constructible<_Tp, _Up>,
    789 			 is_convertible<_Up, _Tp>,
    790 			 __not_<__converts_from_optional<_Tp, _Up>>> = true>
    791 	constexpr
    792 	optional(optional<_Up>&& __t)
    793 	noexcept(is_nothrow_constructible_v<_Tp, _Up>)
    794 	{
    795 	  if (__t)
    796 	    emplace(std::move(*__t));
    797 	}
    798 
    799       template<typename _Up,
    800 	       _Requires<__not_<is_same<_Tp, _Up>>,
    801 			 is_constructible<_Tp, _Up>,
    802 			 __not_<is_convertible<_Up, _Tp>>,
    803 			 __not_<__converts_from_optional<_Tp, _Up>>> = false>
    804 	explicit constexpr
    805 	optional(optional<_Up>&& __t)
    806 	noexcept(is_nothrow_constructible_v<_Tp, _Up>)
    807 	{
    808 	  if (__t)
    809 	    emplace(std::move(*__t));
    810 	}
    811 
    812       template<typename... _Args,
    813 	       _Requires<is_constructible<_Tp, _Args...>> = false>
    814 	explicit constexpr
    815 	optional(in_place_t, _Args&&... __args)
    816 	noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
    817 	: _Base(std::in_place, std::forward<_Args>(__args)...) { }
    818 
    819       template<typename _Up, typename... _Args,
    820 	       _Requires<is_constructible<_Tp,
    821 					  initializer_list<_Up>&,
    822 					  _Args...>> = false>
    823 	explicit constexpr
    824 	optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
    825 	noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
    826 					    _Args...>)
    827 	: _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
    828 
    829 
    830       // Assignment operators.
    831       _GLIBCXX20_CONSTEXPR optional&
    832       operator=(nullopt_t) noexcept
    833       {
    834 	this->_M_reset();
    835 	return *this;
    836       }
    837 
    838       template<typename _Up = _Tp>
    839 	_GLIBCXX20_CONSTEXPR
    840 	enable_if_t<__and_v<__not_self<_Up>,
    841 			    __not_<__and_<is_scalar<_Tp>,
    842 					  is_same<_Tp, decay_t<_Up>>>>,
    843 			    is_constructible<_Tp, _Up>,
    844 			    is_assignable<_Tp&, _Up>>,
    845 		    optional&>
    846 	operator=(_Up&& __u)
    847 	noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
    848 			 is_nothrow_assignable<_Tp&, _Up>>)
    849 	{
    850 	  if (this->_M_is_engaged())
    851 	    this->_M_get() = std::forward<_Up>(__u);
    852 	  else
    853 	    this->_M_construct(std::forward<_Up>(__u));
    854 
    855 	  return *this;
    856 	}
    857 
    858       template<typename _Up>
    859 	_GLIBCXX20_CONSTEXPR
    860 	enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>,
    861 			    is_constructible<_Tp, const _Up&>,
    862 			    is_assignable<_Tp&, const _Up&>,
    863 			    __not_<__converts_from_optional<_Tp, _Up>>,
    864 			    __not_<__assigns_from_optional<_Tp, _Up>>>,
    865 		    optional&>
    866 	operator=(const optional<_Up>& __u)
    867 	noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
    868 			 is_nothrow_assignable<_Tp&, const _Up&>>)
    869 	{
    870 	  if (__u)
    871 	    {
    872 	      if (this->_M_is_engaged())
    873 		this->_M_get() = *__u;
    874 	      else
    875 		this->_M_construct(*__u);
    876 	    }
    877 	  else
    878 	    {
    879 	      this->_M_reset();
    880 	    }
    881 	  return *this;
    882 	}
    883 
    884       template<typename _Up>
    885 	_GLIBCXX20_CONSTEXPR
    886 	enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>,
    887 			    is_constructible<_Tp, _Up>,
    888 			    is_assignable<_Tp&, _Up>,
    889 			    __not_<__converts_from_optional<_Tp, _Up>>,
    890 			    __not_<__assigns_from_optional<_Tp, _Up>>>,
    891 		    optional&>
    892 	operator=(optional<_Up>&& __u)
    893 	noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
    894 			 is_nothrow_assignable<_Tp&, _Up>>)
    895 	{
    896 	  if (__u)
    897 	    {
    898 	      if (this->_M_is_engaged())
    899 		this->_M_get() = std::move(*__u);
    900 	      else
    901 		this->_M_construct(std::move(*__u));
    902 	    }
    903 	  else
    904 	    {
    905 	      this->_M_reset();
    906 	    }
    907 
    908 	  return *this;
    909 	}
    910 
    911       template<typename... _Args>
    912 	_GLIBCXX20_CONSTEXPR
    913 	enable_if_t<is_constructible_v<_Tp, _Args...>, _Tp&>
    914 	emplace(_Args&&... __args)
    915 	noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
    916 	{
    917 	  this->_M_reset();
    918 	  this->_M_construct(std::forward<_Args>(__args)...);
    919 	  return this->_M_get();
    920 	}
    921 
    922       template<typename _Up, typename... _Args>
    923 	_GLIBCXX20_CONSTEXPR
    924 	enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
    925 		    _Tp&>
    926 	emplace(initializer_list<_Up> __il, _Args&&... __args)
    927 	noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
    928 					    _Args...>)
    929 	{
    930 	  this->_M_reset();
    931 	  this->_M_construct(__il, std::forward<_Args>(__args)...);
    932 	  return this->_M_get();
    933 	}
    934 
    935       // Destructor is implicit, implemented in _Optional_base.
    936 
    937       // Swap.
    938       _GLIBCXX20_CONSTEXPR void
    939       swap(optional& __other)
    940       noexcept(is_nothrow_move_constructible_v<_Tp>
    941 	       && is_nothrow_swappable_v<_Tp>)
    942       {
    943 	using std::swap;
    944 
    945 	if (this->_M_is_engaged() && __other._M_is_engaged())
    946 	  swap(this->_M_get(), __other._M_get());
    947 	else if (this->_M_is_engaged())
    948 	  {
    949 	    __other._M_construct(std::move(this->_M_get()));
    950 	    this->_M_destruct();
    951 	  }
    952 	else if (__other._M_is_engaged())
    953 	  {
    954 	    this->_M_construct(std::move(__other._M_get()));
    955 	    __other._M_destruct();
    956 	  }
    957       }
    958 
    959       // Observers.
    960       constexpr const _Tp*
    961       operator->() const noexcept
    962       { return std::__addressof(this->_M_get()); }
    963 
    964       constexpr _Tp*
    965       operator->() noexcept
    966       { return std::__addressof(this->_M_get()); }
    967 
    968       constexpr const _Tp&
    969       operator*() const& noexcept
    970       { return this->_M_get(); }
    971 
    972       constexpr _Tp&
    973       operator*()& noexcept
    974       { return this->_M_get(); }
    975 
    976       constexpr _Tp&&
    977       operator*()&& noexcept
    978       { return std::move(this->_M_get()); }
    979 
    980       constexpr const _Tp&&
    981       operator*() const&& noexcept
    982       { return std::move(this->_M_get()); }
    983 
    984       constexpr explicit operator bool() const noexcept
    985       { return this->_M_is_engaged(); }
    986 
    987       constexpr bool has_value() const noexcept
    988       { return this->_M_is_engaged(); }
    989 
    990       constexpr const _Tp&
    991       value() const&
    992       {
    993 	if (this->_M_is_engaged())
    994 	  return this->_M_get();
    995 	__throw_bad_optional_access();
    996       }
    997 
    998       constexpr _Tp&
    999       value()&
   1000       {
   1001 	if (this->_M_is_engaged())
   1002 	  return this->_M_get();
   1003 	__throw_bad_optional_access();
   1004       }
   1005 
   1006       constexpr _Tp&&
   1007       value()&&
   1008       {
   1009 	if (this->_M_is_engaged())
   1010 	  return std::move(this->_M_get());
   1011 	__throw_bad_optional_access();
   1012       }
   1013 
   1014       constexpr const _Tp&&
   1015       value() const&&
   1016       {
   1017 	if (this->_M_is_engaged())
   1018 	  return std::move(this->_M_get());
   1019 	__throw_bad_optional_access();
   1020       }
   1021 
   1022       template<typename _Up>
   1023 	constexpr _Tp
   1024 	value_or(_Up&& __u) const&
   1025 	{
   1026 	  static_assert(is_copy_constructible_v<_Tp>);
   1027 	  static_assert(is_convertible_v<_Up&&, _Tp>);
   1028 
   1029 	  if (this->_M_is_engaged())
   1030 	    return this->_M_get();
   1031 	  else
   1032 	    return static_cast<_Tp>(std::forward<_Up>(__u));
   1033 	}
   1034 
   1035       template<typename _Up>
   1036 	constexpr _Tp
   1037 	value_or(_Up&& __u) &&
   1038 	{
   1039 	  static_assert(is_move_constructible_v<_Tp>);
   1040 	  static_assert(is_convertible_v<_Up&&, _Tp>);
   1041 
   1042 	  if (this->_M_is_engaged())
   1043 	    return std::move(this->_M_get());
   1044 	  else
   1045 	    return static_cast<_Tp>(std::forward<_Up>(__u));
   1046 	}
   1047 
   1048 #if __cpp_lib_optional >= 202110L
   1049       // [optional.monadic]
   1050 
   1051       template<typename _Fn>
   1052 	constexpr auto
   1053 	and_then(_Fn&& __f) &
   1054 	{
   1055 	  using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp&>>;
   1056 	  static_assert(__is_optional_v<remove_cvref_t<_Up>>);
   1057 	  if (has_value())
   1058 	    return std::__invoke(std::forward<_Fn>(__f), **this);
   1059 	  else
   1060 	    return _Up();
   1061 	}
   1062 
   1063       template<typename _Fn>
   1064 	constexpr auto
   1065 	and_then(_Fn&& __f) const &
   1066 	{
   1067 	  using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp&>>;
   1068 	  static_assert(__is_optional_v<_Up>);
   1069 	  if (has_value())
   1070 	    return std::__invoke(std::forward<_Fn>(__f), **this);
   1071 	  else
   1072 	    return _Up();
   1073 	}
   1074 
   1075       template<typename _Fn>
   1076 	constexpr auto
   1077 	and_then(_Fn&& __f) &&
   1078 	{
   1079 	  using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp>>;
   1080 	  static_assert(__is_optional_v<remove_cvref_t<_Up>>);
   1081 	  if (has_value())
   1082 	    return std::__invoke(std::forward<_Fn>(__f), std::move(**this));
   1083 	  else
   1084 	    return _Up();
   1085 	}
   1086 
   1087       template<typename _Fn>
   1088 	constexpr auto
   1089 	and_then(_Fn&& __f) const &&
   1090 	{
   1091 	  using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp>>;
   1092 	  static_assert(__is_optional_v<remove_cvref_t<_Up>>);
   1093 	  if (has_value())
   1094 	    return std::__invoke(std::forward<_Fn>(__f), std::move(**this));
   1095 	  else
   1096 	    return _Up();
   1097 	}
   1098 
   1099       template<typename _Fn>
   1100 	constexpr auto
   1101 	transform(_Fn&& __f) &
   1102 	{
   1103 	  using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp&>>;
   1104 	  if (has_value())
   1105 	    return optional<_Up>(_Optional_func<_Fn>{__f}, **this);
   1106 	  else
   1107 	    return optional<_Up>();
   1108 	}
   1109 
   1110       template<typename _Fn>
   1111 	constexpr auto
   1112 	transform(_Fn&& __f) const &
   1113 	{
   1114 	  using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp&>>;
   1115 	  if (has_value())
   1116 	    return optional<_Up>(_Optional_func<_Fn>{__f}, **this);
   1117 	  else
   1118 	    return optional<_Up>();
   1119 	}
   1120 
   1121       template<typename _Fn>
   1122 	constexpr auto
   1123 	transform(_Fn&& __f) &&
   1124 	{
   1125 	  using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp>>;
   1126 	  if (has_value())
   1127 	    return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this));
   1128 	  else
   1129 	    return optional<_Up>();
   1130 	}
   1131 
   1132       template<typename _Fn>
   1133 	constexpr auto
   1134 	transform(_Fn&& __f) const &&
   1135 	{
   1136 	  using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp>>;
   1137 	  if (has_value())
   1138 	    return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this));
   1139 	  else
   1140 	    return optional<_Up>();
   1141 	}
   1142 
   1143       template<typename _Fn> requires invocable<_Fn> && copy_constructible<_Tp>
   1144 	constexpr optional
   1145 	or_else(_Fn&& __f) const&
   1146 	{
   1147 	  using _Up = invoke_result_t<_Fn>;
   1148 	  static_assert( is_same_v<remove_cvref_t<_Up>, optional> );
   1149 
   1150 	  if (has_value())
   1151 	    return *this;
   1152 	  else
   1153 	    return std::forward<_Fn>(__f)();
   1154 	}
   1155 
   1156       template<typename _Fn> requires invocable<_Fn> && move_constructible<_Tp>
   1157 	constexpr optional
   1158 	or_else(_Fn&& __f) &&
   1159 	{
   1160 	  using _Up = invoke_result_t<_Fn>;
   1161 	  static_assert( is_same_v<remove_cvref_t<_Up>, optional> );
   1162 
   1163 	  if (has_value())
   1164 	    return std::move(*this);
   1165 	  else
   1166 	    return std::forward<_Fn>(__f)();
   1167 	}
   1168 #endif
   1169 
   1170       _GLIBCXX20_CONSTEXPR void reset() noexcept { this->_M_reset(); }
   1171 
   1172     private:
   1173 #if __cplusplus >= 202002L
   1174       template<typename _Up> friend class optional;
   1175 
   1176       template<typename _Fn, typename _Value>
   1177 	explicit constexpr
   1178 	optional(_Optional_func<_Fn> __f, _Value&& __v)
   1179 	{
   1180 	  this->_M_payload._M_apply(__f, std::forward<_Value>(__v));
   1181 	}
   1182 #endif
   1183     };
   1184 
   1185   template<typename _Tp>
   1186     using __optional_relop_t =
   1187       enable_if_t<is_convertible<_Tp, bool>::value, bool>;
   1188 
   1189   template<typename _Tp, typename _Up>
   1190     using __optional_eq_t = __optional_relop_t<
   1191       decltype(std::declval<const _Tp&>() == std::declval<const _Up&>())
   1192       >;
   1193 
   1194   template<typename _Tp, typename _Up>
   1195     using __optional_ne_t = __optional_relop_t<
   1196       decltype(std::declval<const _Tp&>() != std::declval<const _Up&>())
   1197       >;
   1198 
   1199   template<typename _Tp, typename _Up>
   1200     using __optional_lt_t = __optional_relop_t<
   1201       decltype(std::declval<const _Tp&>() < std::declval<const _Up&>())
   1202       >;
   1203 
   1204   template<typename _Tp, typename _Up>
   1205     using __optional_gt_t = __optional_relop_t<
   1206       decltype(std::declval<const _Tp&>() > std::declval<const _Up&>())
   1207       >;
   1208 
   1209   template<typename _Tp, typename _Up>
   1210     using __optional_le_t = __optional_relop_t<
   1211       decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>())
   1212       >;
   1213 
   1214   template<typename _Tp, typename _Up>
   1215     using __optional_ge_t = __optional_relop_t<
   1216       decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>())
   1217       >;
   1218 
   1219   // Comparisons between optional values.
   1220   template<typename _Tp, typename _Up>
   1221     constexpr auto
   1222     operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
   1223     -> __optional_eq_t<_Tp, _Up>
   1224     {
   1225       return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
   1226 	     && (!__lhs || *__lhs == *__rhs);
   1227     }
   1228 
   1229   template<typename _Tp, typename _Up>
   1230     constexpr auto
   1231     operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
   1232     -> __optional_ne_t<_Tp, _Up>
   1233     {
   1234       return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
   1235 	|| (static_cast<bool>(__lhs) && *__lhs != *__rhs);
   1236     }
   1237 
   1238   template<typename _Tp, typename _Up>
   1239     constexpr auto
   1240     operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
   1241     -> __optional_lt_t<_Tp, _Up>
   1242     {
   1243       return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
   1244     }
   1245 
   1246   template<typename _Tp, typename _Up>
   1247     constexpr auto
   1248     operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
   1249     -> __optional_gt_t<_Tp, _Up>
   1250     {
   1251       return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
   1252     }
   1253 
   1254   template<typename _Tp, typename _Up>
   1255     constexpr auto
   1256     operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
   1257     -> __optional_le_t<_Tp, _Up>
   1258     {
   1259       return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
   1260     }
   1261 
   1262   template<typename _Tp, typename _Up>
   1263     constexpr auto
   1264     operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
   1265     -> __optional_ge_t<_Tp, _Up>
   1266     {
   1267       return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
   1268     }
   1269 
   1270 #ifdef __cpp_lib_three_way_comparison
   1271   template<typename _Tp, three_way_comparable_with<_Tp> _Up>
   1272     constexpr compare_three_way_result_t<_Tp, _Up>
   1273     operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y)
   1274     {
   1275       return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y);
   1276     }
   1277 #endif
   1278 
   1279   // Comparisons with nullopt.
   1280   template<typename _Tp>
   1281     constexpr bool
   1282     operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
   1283     { return !__lhs; }
   1284 
   1285 #ifdef __cpp_lib_three_way_comparison
   1286   template<typename _Tp>
   1287     constexpr strong_ordering
   1288     operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept
   1289     { return bool(__x) <=> false; }
   1290 #else
   1291   template<typename _Tp>
   1292     constexpr bool
   1293     operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
   1294     { return !__rhs; }
   1295 
   1296   template<typename _Tp>
   1297     constexpr bool
   1298     operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
   1299     { return static_cast<bool>(__lhs); }
   1300 
   1301   template<typename _Tp>
   1302     constexpr bool
   1303     operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
   1304     { return static_cast<bool>(__rhs); }
   1305 
   1306   template<typename _Tp>
   1307     constexpr bool
   1308     operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
   1309     { return false; }
   1310 
   1311   template<typename _Tp>
   1312     constexpr bool
   1313     operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
   1314     { return static_cast<bool>(__rhs); }
   1315 
   1316   template<typename _Tp>
   1317     constexpr bool
   1318     operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
   1319     { return static_cast<bool>(__lhs); }
   1320 
   1321   template<typename _Tp>
   1322     constexpr bool
   1323     operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
   1324     { return false; }
   1325 
   1326   template<typename _Tp>
   1327     constexpr bool
   1328     operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
   1329     { return !__lhs; }
   1330 
   1331   template<typename _Tp>
   1332     constexpr bool
   1333     operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
   1334     { return true; }
   1335 
   1336   template<typename _Tp>
   1337     constexpr bool
   1338     operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
   1339     { return true; }
   1340 
   1341   template<typename _Tp>
   1342     constexpr bool
   1343     operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
   1344     { return !__rhs; }
   1345 #endif // three-way-comparison
   1346 
   1347   // Comparisons with value type.
   1348   template<typename _Tp, typename _Up>
   1349     constexpr auto
   1350     operator==(const optional<_Tp>& __lhs, const _Up& __rhs)
   1351     -> __optional_eq_t<_Tp, _Up>
   1352     { return __lhs && *__lhs == __rhs; }
   1353 
   1354   template<typename _Tp, typename _Up>
   1355     constexpr auto
   1356     operator==(const _Up& __lhs, const optional<_Tp>& __rhs)
   1357     -> __optional_eq_t<_Up, _Tp>
   1358     { return __rhs && __lhs == *__rhs; }
   1359 
   1360   template<typename _Tp, typename _Up>
   1361     constexpr auto
   1362     operator!=(const optional<_Tp>& __lhs, const _Up& __rhs)
   1363     -> __optional_ne_t<_Tp, _Up>
   1364     { return !__lhs || *__lhs != __rhs; }
   1365 
   1366   template<typename _Tp, typename _Up>
   1367     constexpr auto
   1368     operator!=(const _Up& __lhs, const optional<_Tp>& __rhs)
   1369     -> __optional_ne_t<_Up, _Tp>
   1370     { return !__rhs || __lhs != *__rhs; }
   1371 
   1372   template<typename _Tp, typename _Up>
   1373     constexpr auto
   1374     operator<(const optional<_Tp>& __lhs, const _Up& __rhs)
   1375     -> __optional_lt_t<_Tp, _Up>
   1376     { return !__lhs || *__lhs < __rhs; }
   1377 
   1378   template<typename _Tp, typename _Up>
   1379     constexpr auto
   1380     operator<(const _Up& __lhs, const optional<_Tp>& __rhs)
   1381     -> __optional_lt_t<_Up, _Tp>
   1382     { return __rhs && __lhs < *__rhs; }
   1383 
   1384   template<typename _Tp, typename _Up>
   1385     constexpr auto
   1386     operator>(const optional<_Tp>& __lhs, const _Up& __rhs)
   1387     -> __optional_gt_t<_Tp, _Up>
   1388     { return __lhs && *__lhs > __rhs; }
   1389 
   1390   template<typename _Tp, typename _Up>
   1391     constexpr auto
   1392     operator>(const _Up& __lhs, const optional<_Tp>& __rhs)
   1393     -> __optional_gt_t<_Up, _Tp>
   1394     { return !__rhs || __lhs > *__rhs; }
   1395 
   1396   template<typename _Tp, typename _Up>
   1397     constexpr auto
   1398     operator<=(const optional<_Tp>& __lhs, const _Up& __rhs)
   1399     -> __optional_le_t<_Tp, _Up>
   1400     { return !__lhs || *__lhs <= __rhs; }
   1401 
   1402   template<typename _Tp, typename _Up>
   1403     constexpr auto
   1404     operator<=(const _Up& __lhs, const optional<_Tp>& __rhs)
   1405     -> __optional_le_t<_Up, _Tp>
   1406     { return __rhs && __lhs <= *__rhs; }
   1407 
   1408   template<typename _Tp, typename _Up>
   1409     constexpr auto
   1410     operator>=(const optional<_Tp>& __lhs, const _Up& __rhs)
   1411     -> __optional_ge_t<_Tp, _Up>
   1412     { return __lhs && *__lhs >= __rhs; }
   1413 
   1414   template<typename _Tp, typename _Up>
   1415     constexpr auto
   1416     operator>=(const _Up& __lhs, const optional<_Tp>& __rhs)
   1417     -> __optional_ge_t<_Up, _Tp>
   1418     { return !__rhs || __lhs >= *__rhs; }
   1419 
   1420 #ifdef __cpp_lib_three_way_comparison
   1421   template<typename _Tp, typename _Up>
   1422     requires (!__is_optional_v<_Up>)
   1423       && three_way_comparable_with<_Up, _Tp>
   1424     constexpr compare_three_way_result_t<_Tp, _Up>
   1425     operator<=>(const optional<_Tp>& __x, const _Up& __v)
   1426     { return bool(__x) ? *__x <=> __v : strong_ordering::less; }
   1427 #endif
   1428 
   1429   // Swap and creation functions.
   1430 
   1431   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   1432   // 2748. swappable traits for optionals
   1433   template<typename _Tp>
   1434     _GLIBCXX20_CONSTEXPR
   1435     inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
   1436     swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
   1437     noexcept(noexcept(__lhs.swap(__rhs)))
   1438     { __lhs.swap(__rhs); }
   1439 
   1440   template<typename _Tp>
   1441     enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
   1442     swap(optional<_Tp>&, optional<_Tp>&) = delete;
   1443 
   1444   template<typename _Tp>
   1445     constexpr
   1446     enable_if_t<is_constructible_v<decay_t<_Tp>, _Tp>,
   1447 		optional<decay_t<_Tp>>>
   1448     make_optional(_Tp&& __t)
   1449     noexcept(is_nothrow_constructible_v<optional<decay_t<_Tp>>, _Tp>)
   1450     { return optional<decay_t<_Tp>>{ std::forward<_Tp>(__t) }; }
   1451 
   1452   template<typename _Tp, typename... _Args>
   1453     constexpr
   1454     enable_if_t<is_constructible_v<_Tp, _Args...>,
   1455 		optional<_Tp>>
   1456     make_optional(_Args&&... __args)
   1457     noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
   1458     { return optional<_Tp>{ in_place, std::forward<_Args>(__args)... }; }
   1459 
   1460   template<typename _Tp, typename _Up, typename... _Args>
   1461     constexpr
   1462     enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
   1463 		optional<_Tp>>
   1464     make_optional(initializer_list<_Up> __il, _Args&&... __args)
   1465     noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>)
   1466     { return optional<_Tp>{ in_place, __il, std::forward<_Args>(__args)... }; }
   1467 
   1468   // Hash.
   1469 
   1470   template<typename _Tp, typename _Up = remove_const_t<_Tp>,
   1471 	   bool = __poison_hash<_Up>::__enable_hash_call>
   1472     struct __optional_hash_call_base
   1473     {
   1474       size_t
   1475       operator()(const optional<_Tp>& __t) const
   1476       noexcept(noexcept(hash<_Up>{}(*__t)))
   1477       {
   1478 	// We pick an arbitrary hash for disengaged optionals which hopefully
   1479 	// usual values of _Tp won't typically hash to.
   1480 	constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
   1481 	return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash;
   1482       }
   1483     };
   1484 
   1485   template<typename _Tp, typename _Up>
   1486     struct __optional_hash_call_base<_Tp, _Up, false> {};
   1487 
   1488   template<typename _Tp>
   1489     struct hash<optional<_Tp>>
   1490     : private __poison_hash<remove_const_t<_Tp>>,
   1491       public __optional_hash_call_base<_Tp>
   1492     {
   1493       using result_type [[__deprecated__]] = size_t;
   1494       using argument_type [[__deprecated__]] = optional<_Tp>;
   1495     };
   1496 
   1497   template<typename _Tp>
   1498     struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>>
   1499     { };
   1500 
   1501   /// @}
   1502 
   1503 #if __cpp_deduction_guides >= 201606
   1504   template <typename _Tp> optional(_Tp) -> optional<_Tp>;
   1505 #endif
   1506 
   1507 _GLIBCXX_END_NAMESPACE_VERSION
   1508 } // namespace std
   1509 
   1510 #endif // C++17
   1511 
   1512 #endif // _GLIBCXX_OPTIONAL
   1513