Home | History | Annotate | Line # | Download | only in std
expected revision 1.1
      1 // <expected> -*- C++ -*-
      2 
      3 // Copyright The GNU Toolchain Authors.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file include/expected
     26  *  This is a Standard C++ Library header.
     27  */
     28 
     29 #ifndef _GLIBCXX_EXPECTED
     30 #define _GLIBCXX_EXPECTED
     31 
     32 #pragma GCC system_header
     33 
     34 #if __cplusplus > 202002L && __cpp_concepts >= 202002L
     35 
     36 #include <initializer_list>
     37 #include <bits/exception.h>	// exception
     38 #include <bits/stl_construct.h>	// construct_at
     39 #include <bits/utility.h>	// in_place_t
     40 
     41 namespace std _GLIBCXX_VISIBILITY(default)
     42 {
     43 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     44 
     45   /**
     46    * @defgroup expected_values Expected values
     47    * @addtogroup utilities
     48    * @since C++23
     49    * @{
     50    */
     51 
     52 #define __cpp_lib_expected 202202L
     53 
     54   /// Discriminated union that holds an expected value or an error value.
     55   /**
     56    * @since C++23
     57    */
     58   template<typename _Tp, typename _Er>
     59     class expected;
     60 
     61   /// Wrapper type used to pass an error value to a `std::expected`.
     62   /**
     63    * @since C++23
     64    */
     65   template<typename _Er>
     66     class unexpected;
     67 
     68   /// Exception thrown by std::expected when the value() is not present.
     69   /**
     70    * @since C++23
     71    */
     72   template<typename _Er>
     73     class bad_expected_access;
     74 
     75   template<>
     76     class bad_expected_access<void> : public exception
     77     {
     78     protected:
     79       bad_expected_access() noexcept { }
     80       bad_expected_access(const bad_expected_access&) = default;
     81       bad_expected_access(bad_expected_access&&) = default;
     82       bad_expected_access& operator=(const bad_expected_access&) = default;
     83       bad_expected_access& operator=(bad_expected_access&&) = default;
     84       ~bad_expected_access() = default;
     85 
     86     public:
     87 
     88       [[nodiscard]]
     89       const char*
     90       what() const noexcept override
     91       { return "bad access to std::expected without expected value"; }
     92     };
     93 
     94   template<typename _Er>
     95     class bad_expected_access : public bad_expected_access<void> {
     96     public:
     97       explicit
     98       bad_expected_access(_Er __e) : _M_unex(std::move(__e)) { }
     99 
    100       // XXX const char* what() const noexcept override;
    101 
    102       [[nodiscard]]
    103       _Er&
    104       error() & noexcept
    105       { return _M_unex; }
    106 
    107       [[nodiscard]]
    108       const _Er&
    109       error() const & noexcept
    110       { return _M_unex; }
    111 
    112       [[nodiscard]]
    113       _Er&&
    114       error() && noexcept
    115       { return std::move(_M_unex); }
    116 
    117       [[nodiscard]]
    118       const _Er&&
    119       error() const && noexcept
    120       { return std::move(_M_unex); }
    121 
    122     private:
    123       _Er _M_unex;
    124     };
    125 
    126   /// Tag type for constructing unexpected values in a std::expected
    127   /**
    128    * @since C++23
    129    */
    130   struct unexpect_t
    131   {
    132     explicit unexpect_t() = default;
    133   };
    134 
    135   /// Tag for constructing unexpected values in a std::expected
    136   /**
    137    * @since C++23
    138    */
    139   inline constexpr unexpect_t unexpect{};
    140 
    141 /// @cond undoc
    142 namespace __expected
    143 {
    144   template<typename _Tp>
    145     constexpr bool __is_expected = false;
    146   template<typename _Tp, typename _Er>
    147     constexpr bool __is_expected<expected<_Tp, _Er>> = true;
    148 
    149   template<typename _Tp>
    150     constexpr bool __is_unexpected = false;
    151   template<typename _Tp>
    152     constexpr bool __is_unexpected<unexpected<_Tp>> = true;
    153 
    154   template<typename _Er>
    155     concept __can_be_unexpected
    156       = is_object_v<_Er> && (!is_array_v<_Er>)
    157 	  && (!__expected::__is_unexpected<_Er>)
    158 	  && (!is_const_v<_Er>) && (!is_volatile_v<_Er>);
    159 }
    160 /// @endcond
    161 
    162   template<typename _Er>
    163     class unexpected
    164     {
    165       static_assert( __expected::__can_be_unexpected<_Er> );
    166 
    167     public:
    168       constexpr unexpected(const unexpected&) = default;
    169       constexpr unexpected(unexpected&&) = default;
    170 
    171       template<typename _Err = _Er>
    172 	requires (!is_same_v<remove_cvref_t<_Err>, unexpected>)
    173 	  && (!is_same_v<remove_cvref_t<_Err>, in_place_t>)
    174 	  && is_constructible_v<_Er, _Err>
    175 	constexpr explicit
    176 	unexpected(_Err&& __e)
    177 	noexcept(is_nothrow_constructible_v<_Er, _Err>)
    178 	: _M_unex(std::forward<_Err>(__e))
    179 	{ }
    180 
    181       template<typename... _Args>
    182 	requires is_constructible_v<_Er, _Args...>
    183 	constexpr explicit
    184 	unexpected(in_place_t, _Args&&... __args)
    185 	noexcept(is_nothrow_constructible_v<_Er, _Args...>)
    186 	: _M_unex(std::forward<_Args>(__args)...)
    187 	{ }
    188 
    189       template<typename _Up, typename... _Args>
    190 	requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
    191 	constexpr explicit
    192 	unexpected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
    193 	noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
    194 					    _Args...>)
    195 	: _M_unex(__il, std::forward<_Args>(__args)...)
    196 	{ }
    197 
    198       constexpr unexpected& operator=(const unexpected&) = default;
    199       constexpr unexpected& operator=(unexpected&&) = default;
    200 
    201 
    202       [[nodiscard]]
    203       constexpr const _Er&
    204       error() const & noexcept { return _M_unex; }
    205 
    206       [[nodiscard]]
    207       constexpr _Er&
    208       error() & noexcept { return _M_unex; }
    209 
    210       [[nodiscard]]
    211       constexpr const _Er&&
    212       error() const && noexcept { return std::move(_M_unex); }
    213 
    214       [[nodiscard]]
    215       constexpr _Er&&
    216       error() && noexcept { return std::move(_M_unex); }
    217 
    218       constexpr void
    219       swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Er>)
    220       requires is_swappable_v<_Er>
    221       {
    222 	using std::swap;
    223 	swap(_M_unex, __other._M_unex);
    224       }
    225 
    226       template<typename _Err>
    227 	[[nodiscard]]
    228 	friend constexpr bool
    229 	operator==(const unexpected& __x, const unexpected<_Err>& __y)
    230 	{ return __x._M_unex == __y.error(); }
    231 
    232       friend constexpr void
    233       swap(unexpected& __x, unexpected& __y) noexcept(noexcept(__x.swap(__y)))
    234       requires is_swappable_v<_Er>
    235       { __x.swap(__y); }
    236 
    237     private:
    238       _Er _M_unex;
    239     };
    240 
    241   template<typename _Er> unexpected(_Er) -> unexpected<_Er>;
    242 
    243 /// @cond undoc
    244 namespace __expected
    245 {
    246   template<typename _Tp>
    247     struct _Guard
    248     {
    249       static_assert( is_nothrow_move_constructible_v<_Tp> );
    250 
    251       constexpr explicit
    252       _Guard(_Tp& __x)
    253       : _M_guarded(__builtin_addressof(__x)), _M_tmp(std::move(__x)) // nothrow
    254       { std::destroy_at(_M_guarded); }
    255 
    256       constexpr
    257       ~_Guard()
    258       {
    259 	if (_M_guarded) [[unlikely]]
    260 	  std::construct_at(_M_guarded, std::move(_M_tmp));
    261       }
    262 
    263       _Guard(const _Guard&) = delete;
    264       _Guard& operator=(const _Guard&) = delete;
    265 
    266       constexpr _Tp&&
    267       release() noexcept
    268       {
    269 	_M_guarded = nullptr;
    270 	return std::move(_M_tmp);
    271       }
    272 
    273     private:
    274       _Tp* _M_guarded;
    275       _Tp _M_tmp;
    276     };
    277 
    278   // reinit-expected helper from [expected.object.assign]
    279   template<typename _Tp, typename _Up, typename _Vp>
    280     constexpr void
    281     __reinit(_Tp* __newval, _Up* __oldval, _Vp&& __arg)
    282     noexcept(is_nothrow_constructible_v<_Tp, _Vp>)
    283     {
    284       if constexpr (is_nothrow_constructible_v<_Tp, _Vp>)
    285 	{
    286 	  std::destroy_at(__oldval);
    287 	  std::construct_at(__newval, std::forward<_Vp>(__arg));
    288 	}
    289       else if constexpr (is_nothrow_move_constructible_v<_Tp>)
    290 	{
    291 	  _Tp __tmp(std::forward<_Vp>(__arg)); // might throw
    292 	  std::destroy_at(__oldval);
    293 	  std::construct_at(__newval, std::move(__tmp));
    294 	}
    295       else
    296 	{
    297 	  _Guard<_Up> __guard(*__oldval);
    298 	  std::construct_at(__newval, std::forward<_Vp>(__arg)); // might throw
    299 	  __guard.release();
    300 	}
    301     }
    302 }
    303 /// @endcond
    304 
    305   template<typename _Tp, typename _Er>
    306     class expected
    307     {
    308       static_assert( ! is_reference_v<_Tp> );
    309       static_assert( ! is_function_v<_Tp> );
    310       static_assert( ! is_same_v<remove_cv_t<_Tp>, in_place_t> );
    311       static_assert( ! is_same_v<remove_cv_t<_Tp>, unexpect_t> );
    312       static_assert( ! __expected::__is_unexpected<remove_cv_t<_Tp>> );
    313       static_assert( __expected::__can_be_unexpected<_Er> );
    314 
    315       template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
    316 	static constexpr bool __cons_from_expected
    317 	  = __or_v<is_constructible<_Tp, expected<_Up, _Err>&>,
    318 		   is_constructible<_Tp, expected<_Up, _Err>>,
    319 		   is_constructible<_Tp, const expected<_Up, _Err>&>,
    320 		   is_constructible<_Tp, const expected<_Up, _Err>>,
    321 		   is_convertible<expected<_Up, _Err>&, _Tp>,
    322 		   is_convertible<expected<_Up, _Err>, _Tp>,
    323 		   is_convertible<const expected<_Up, _Err>&, _Tp>,
    324 		   is_convertible<const expected<_Up, _Err>, _Tp>,
    325 		   is_constructible<_Unex, expected<_Up, _Err>&>,
    326 		   is_constructible<_Unex, expected<_Up, _Err>>,
    327 		   is_constructible<_Unex, const expected<_Up, _Err>&>,
    328 		   is_constructible<_Unex, const expected<_Up, _Err>>
    329 		  >;
    330 
    331       template<typename _Up, typename _Err>
    332 	constexpr static bool __explicit_conv
    333 	  = __or_v<__not_<is_convertible<_Up, _Tp>>,
    334 		   __not_<is_convertible<_Err, _Er>>
    335 		  >;
    336 
    337     public:
    338       using value_type = _Tp;
    339       using error_type = _Er;
    340       using unexpected_type = unexpected<_Er>;
    341 
    342       template<typename _Up>
    343 	using rebind = expected<_Up, error_type>;
    344 
    345       constexpr
    346       expected()
    347       noexcept(is_nothrow_default_constructible_v<_Tp>)
    348       requires is_default_constructible_v<_Tp>
    349       : _M_val(), _M_has_value(true)
    350       { }
    351 
    352       expected(const expected&) = default;
    353 
    354       constexpr
    355       expected(const expected& __x)
    356       noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
    357 		       is_nothrow_copy_constructible<_Er>>)
    358       requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Er>
    359       && (!is_trivially_copy_constructible_v<_Tp>
    360 	  || !is_trivially_copy_constructible_v<_Er>)
    361       : _M_has_value(__x._M_has_value)
    362       {
    363 	if (_M_has_value)
    364 	  std::construct_at(__builtin_addressof(_M_val), __x._M_val);
    365 	else
    366 	  std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
    367       }
    368 
    369       expected(expected&&) = default;
    370 
    371       constexpr
    372       expected(expected&& __x)
    373       noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
    374 		       is_nothrow_move_constructible<_Er>>)
    375       requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Er>
    376       && (!is_trivially_move_constructible_v<_Tp>
    377 	  || !is_trivially_move_constructible_v<_Er>)
    378       : _M_has_value(__x._M_has_value)
    379       {
    380 	if (_M_has_value)
    381 	  std::construct_at(__builtin_addressof(_M_val),
    382 			    std::move(__x)._M_val);
    383 	else
    384 	  std::construct_at(__builtin_addressof(_M_unex),
    385 			    std::move(__x)._M_unex);
    386       }
    387 
    388       template<typename _Up, typename _Gr>
    389 	requires is_constructible_v<_Tp, const _Up&>
    390 	      && is_constructible_v<_Er, const _Gr&>
    391 	      && (!__cons_from_expected<_Up, _Gr>)
    392 	constexpr explicit(__explicit_conv<const _Up&, const _Gr&>)
    393 	expected(const expected<_Up, _Gr>& __x)
    394 	noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
    395 			 is_nothrow_constructible<_Er, const _Gr&>>)
    396 	: _M_has_value(__x._M_has_value)
    397 	{
    398 	  if (_M_has_value)
    399 	    std::construct_at(__builtin_addressof(_M_val), __x._M_val);
    400 	  else
    401 	    std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
    402 	}
    403 
    404       template<typename _Up, typename _Gr>
    405 	requires is_constructible_v<_Tp, _Up>
    406 	      && is_constructible_v<_Er, _Gr>
    407 	      && (!__cons_from_expected<_Up, _Gr>)
    408 	constexpr explicit(__explicit_conv<_Up, _Gr>)
    409 	expected(expected<_Up, _Gr>&& __x)
    410 	noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
    411 			 is_nothrow_constructible<_Er, _Gr>>)
    412 	: _M_has_value(__x._M_has_value)
    413 	{
    414 	  if (_M_has_value)
    415 	    std::construct_at(__builtin_addressof(_M_val),
    416 			      std::move(__x)._M_val);
    417 	  else
    418 	    std::construct_at(__builtin_addressof(_M_unex),
    419 			      std::move(__x)._M_unex);
    420 	}
    421 
    422       template<typename _Up = _Tp>
    423 	requires (!is_same_v<remove_cvref_t<_Up>, expected>)
    424 	  && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
    425 	  && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
    426 	  && is_constructible_v<_Tp, _Up>
    427 	constexpr explicit(!is_convertible_v<_Up, _Tp>)
    428 	expected(_Up&& __v)
    429 	noexcept(is_nothrow_constructible_v<_Tp, _Up>)
    430 	: _M_val(std::forward<_Up>(__v)), _M_has_value(true)
    431 	{ }
    432 
    433       template<typename _Gr = _Er>
    434 	requires is_constructible_v<_Er, const _Gr&>
    435 	constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
    436 	expected(const unexpected<_Gr>& __u)
    437 	noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
    438 	: _M_unex(__u.error()), _M_has_value(false)
    439 	{ }
    440 
    441       template<typename _Gr = _Er>
    442 	requires is_constructible_v<_Er, _Gr>
    443 	constexpr explicit(!is_convertible_v<_Gr, _Er>)
    444 	expected(unexpected<_Gr>&& __u)
    445 	noexcept(is_nothrow_constructible_v<_Er, _Gr>)
    446 	: _M_unex(std::move(__u).error()), _M_has_value(false)
    447 	{ }
    448 
    449       template<typename... _Args>
    450 	requires is_constructible_v<_Tp, _Args...>
    451 	constexpr explicit
    452 	expected(in_place_t, _Args&&... __args)
    453 	noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
    454 	: _M_val(std::forward<_Args>(__args)...), _M_has_value(true)
    455 	{ }
    456 
    457       template<typename _Up, typename... _Args>
    458 	requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
    459 	constexpr explicit
    460 	expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
    461 	noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
    462 					    _Args...>)
    463 	: _M_val(__il, std::forward<_Args>(__args)...), _M_has_value(true)
    464 	{ }
    465 
    466       template<typename... _Args>
    467 	requires is_constructible_v<_Er, _Args...>
    468 	constexpr explicit
    469 	expected(unexpect_t, _Args&&... __args)
    470 	noexcept(is_nothrow_constructible_v<_Er, _Args...>)
    471 	: _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
    472 	{ }
    473 
    474       template<typename _Up, typename... _Args>
    475 	requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
    476 	constexpr explicit
    477 	expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
    478 	noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
    479 					    _Args...>)
    480 	: _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
    481 	{ }
    482 
    483       constexpr ~expected() = default;
    484 
    485       constexpr ~expected()
    486       requires (!is_trivially_destructible_v<_Tp>)
    487 	    || (!is_trivially_destructible_v<_Er>)
    488       {
    489 	if (_M_has_value)
    490 	  std::destroy_at(__builtin_addressof(_M_val));
    491 	else
    492 	  std::destroy_at(__builtin_addressof(_M_unex));
    493       }
    494 
    495       // assignment
    496 
    497       expected& operator=(const expected&) = delete;
    498 
    499       constexpr expected&
    500       operator=(const expected& __x)
    501       noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
    502 		       is_nothrow_copy_constructible<_Er>,
    503 		       is_nothrow_copy_assignable<_Tp>,
    504 		       is_nothrow_copy_assignable<_Er>>)
    505       requires is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp>
    506 	    && is_copy_assignable_v<_Er> && is_copy_constructible_v<_Er>
    507 	    && (is_nothrow_move_constructible_v<_Tp>
    508 		|| is_nothrow_move_constructible_v<_Er>)
    509       {
    510 	if (__x._M_has_value)
    511 	  this->_M_assign_val(__x._M_val);
    512 	else
    513 	  this->_M_assign_unex(__x._M_unex);
    514 	return *this;
    515       }
    516 
    517       constexpr expected&
    518       operator=(expected&& __x)
    519       noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
    520 		       is_nothrow_move_constructible<_Er>,
    521 		       is_nothrow_move_assignable<_Tp>,
    522 		       is_nothrow_move_assignable<_Er>>)
    523       requires is_move_assignable_v<_Tp> && is_move_constructible_v<_Tp>
    524 	    && is_move_assignable_v<_Er> && is_move_constructible_v<_Er>
    525 	    && (is_nothrow_move_constructible_v<_Tp>
    526 		|| is_nothrow_move_constructible_v<_Er>)
    527       {
    528 	if (__x._M_has_value)
    529 	  _M_assign_val(std::move(__x._M_val));
    530 	else
    531 	  _M_assign_unex(std::move(__x._M_unex));
    532 	return *this;
    533       }
    534 
    535       template<typename _Up = _Tp>
    536 	requires (!is_same_v<expected, remove_cvref_t<_Up>>)
    537 	      && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
    538 	      && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up>
    539 	      && (is_nothrow_constructible_v<_Tp, _Up>
    540 		  || is_nothrow_move_constructible_v<_Tp>
    541 		  || is_nothrow_move_constructible_v<_Er>)
    542 	constexpr expected&
    543 	operator=(_Up&& __v)
    544 	{
    545 	  _M_assign_val(std::forward<_Up>(__v));
    546 	  return *this;
    547 	}
    548 
    549       template<typename _Gr>
    550 	requires is_constructible_v<_Er, const _Gr&>
    551 	      && is_assignable_v<_Er&, const _Gr&>
    552 	      && (is_nothrow_constructible_v<_Er, const _Gr&>
    553 		  || is_nothrow_move_constructible_v<_Tp>
    554 		  || is_nothrow_move_constructible_v<_Er>)
    555 	constexpr expected&
    556 	operator=(const unexpected<_Gr>& __e)
    557 	{
    558 	  _M_assign_unex(__e.error());
    559 	  return *this;
    560 	}
    561 
    562       template<typename _Gr>
    563 	requires is_constructible_v<_Er, _Gr>
    564 	      && is_assignable_v<_Er&, _Gr>
    565 	      && (is_nothrow_constructible_v<_Er, _Gr>
    566 		  || is_nothrow_move_constructible_v<_Tp>
    567 		  || is_nothrow_move_constructible_v<_Er>)
    568 	constexpr expected&
    569 	operator=(unexpected<_Gr>&& __e)
    570 	{
    571 	  _M_assign_unex(std::move(__e).error());
    572 	  return *this;
    573 	}
    574 
    575       // modifiers
    576 
    577       template<typename... _Args>
    578 	requires is_nothrow_constructible_v<_Tp, _Args...>
    579 	constexpr _Tp&
    580 	emplace(_Args&&... __args) noexcept
    581 	{
    582 	  if (_M_has_value)
    583 	    std::destroy_at(__builtin_addressof(_M_val));
    584 	  else
    585 	    {
    586 	      std::destroy_at(__builtin_addressof(_M_unex));
    587 	      _M_has_value = true;
    588 	    }
    589 	  std::construct_at(__builtin_addressof(_M_val),
    590 			    std::forward<_Args>(__args)...);
    591 	  return _M_val;
    592 	}
    593 
    594       template<typename _Up, typename... _Args>
    595 	requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
    596 					    _Args...>
    597 	constexpr _Tp&
    598 	emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept
    599 	{
    600 	  if (_M_has_value)
    601 	    std::destroy_at(__builtin_addressof(_M_val));
    602 	  else
    603 	    {
    604 	      std::destroy_at(__builtin_addressof(_M_unex));
    605 	      _M_has_value = true;
    606 	    }
    607 	  std::construct_at(__builtin_addressof(_M_val),
    608 			    __il, std::forward<_Args>(__args)...);
    609 	  return _M_val;
    610 	}
    611 
    612       // swap
    613       constexpr void
    614       swap(expected& __x)
    615       noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
    616 		       is_nothrow_move_constructible<_Er>,
    617 		       is_nothrow_swappable<_Tp&>,
    618 		       is_nothrow_swappable<_Er&>>)
    619       requires is_swappable_v<_Tp> && is_swappable_v<_Er>
    620 	    && is_move_constructible_v<_Tp>
    621 	    && is_move_constructible_v<_Er>
    622 	    && (is_nothrow_move_constructible_v<_Tp>
    623 		|| is_nothrow_move_constructible_v<_Er>)
    624       {
    625 	if (_M_has_value)
    626 	  {
    627 	    if (__x._M_has_value)
    628 	      {
    629 		using std::swap;
    630 		swap(_M_val, __x._M_val);
    631 	      }
    632 	    else
    633 	      this->_M_swap_val_unex(__x);
    634 	  }
    635 	else
    636 	  {
    637 	    if (__x._M_has_value)
    638 	      __x._M_swap_val_unex(*this);
    639 	    else
    640 	      {
    641 		using std::swap;
    642 		swap(_M_unex, __x._M_unex);
    643 	      }
    644 	  }
    645       }
    646 
    647       // observers
    648 
    649       [[nodiscard]]
    650       constexpr const _Tp*
    651       operator->() const noexcept
    652       {
    653 	__glibcxx_assert(_M_has_value);
    654 	return __builtin_addressof(_M_val);
    655       }
    656 
    657       [[nodiscard]]
    658       constexpr _Tp*
    659       operator->() noexcept
    660       {
    661 	__glibcxx_assert(_M_has_value);
    662 	return __builtin_addressof(_M_val);
    663       }
    664 
    665       [[nodiscard]]
    666       constexpr const _Tp&
    667       operator*() const & noexcept
    668       {
    669 	__glibcxx_assert(_M_has_value);
    670 	return _M_val;
    671       }
    672 
    673       [[nodiscard]]
    674       constexpr _Tp&
    675       operator*() & noexcept
    676       {
    677 	__glibcxx_assert(_M_has_value);
    678 	return _M_val;
    679       }
    680 
    681       [[nodiscard]]
    682       constexpr const _Tp&&
    683       operator*() const && noexcept
    684       {
    685 	__glibcxx_assert(_M_has_value);
    686 	return std::move(_M_val);
    687       }
    688 
    689       [[nodiscard]]
    690       constexpr _Tp&&
    691       operator*() && noexcept
    692       {
    693 	__glibcxx_assert(_M_has_value);
    694 	return std::move(_M_val);
    695       }
    696 
    697       [[nodiscard]]
    698       constexpr explicit
    699       operator bool() const noexcept { return _M_has_value; }
    700 
    701       [[nodiscard]]
    702       constexpr bool has_value() const noexcept { return _M_has_value; }
    703 
    704       constexpr const _Tp&
    705       value() const &
    706       {
    707 	if (_M_has_value) [[likely]]
    708 	  return _M_val;
    709 	_GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
    710       }
    711 
    712       constexpr _Tp&
    713       value() &
    714       {
    715 	if (_M_has_value) [[likely]]
    716 	  return _M_val;
    717 	const auto& __unex = _M_unex;
    718 	_GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(__unex));
    719       }
    720 
    721       constexpr const _Tp&&
    722       value() const &&
    723       {
    724 	if (_M_has_value) [[likely]]
    725 	  return std::move(_M_val);
    726 	_GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(
    727 				  std::move(_M_unex)));
    728       }
    729 
    730       constexpr _Tp&&
    731       value() &&
    732       {
    733 	if (_M_has_value) [[likely]]
    734 	  return std::move(_M_val);
    735 	_GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(
    736 				  std::move(_M_unex)));
    737       }
    738 
    739       constexpr const _Er&
    740       error() const & noexcept
    741       {
    742 	__glibcxx_assert(!_M_has_value);
    743 	return _M_unex;
    744       }
    745 
    746       constexpr _Er&
    747       error() & noexcept
    748       {
    749 	__glibcxx_assert(!_M_has_value);
    750 	return _M_unex;
    751       }
    752 
    753       constexpr const _Er&&
    754       error() const && noexcept
    755       {
    756 	__glibcxx_assert(!_M_has_value);
    757 	return std::move(_M_unex);
    758       }
    759 
    760       constexpr _Er&&
    761       error() && noexcept
    762       {
    763 	__glibcxx_assert(!_M_has_value);
    764 	return std::move(_M_unex);
    765       }
    766 
    767       template<typename _Up>
    768 	constexpr _Tp
    769 	value_or(_Up&& __v) const &
    770 	noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
    771 			 is_nothrow_convertible<_Up, _Tp>>)
    772 	{
    773 	  static_assert( is_copy_constructible_v<_Tp> );
    774 	  static_assert( is_convertible_v<_Up, _Tp> );
    775 
    776 	  if (_M_has_value)
    777 	    return _M_val;
    778 	  return static_cast<_Tp>(std::forward<_Up>(__v));
    779 	}
    780 
    781       template<typename _Up>
    782 	constexpr _Tp
    783 	value_or(_Up&& __v) &&
    784 	noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
    785 			 is_nothrow_convertible<_Up, _Tp>>)
    786 	{
    787 	  static_assert( is_move_constructible_v<_Tp> );
    788 	  static_assert( is_convertible_v<_Up, _Tp> );
    789 
    790 	  if (_M_has_value)
    791 	    return std::move(_M_val);
    792 	  return static_cast<_Tp>(std::forward<_Up>(__v));
    793 	}
    794 
    795       // equality operators
    796 
    797       template<typename _Up, typename _Er2>
    798 	requires (!is_void_v<_Up>)
    799 	friend constexpr bool
    800 	operator==(const expected& __x, const expected<_Up, _Er2>& __y)
    801 	// FIXME: noexcept(noexcept(bool(*__x == *__y))
    802 		  // && noexcept(bool(__x.error() == __y.error())))
    803 	{
    804 	  if (__x.has_value())
    805 	    return __y.has_value() && bool(*__x == *__y);
    806 	  else
    807 	    return !__y.has_value() && bool(__x.error() == __y.error());
    808 	}
    809 
    810       template<typename _Up>
    811 	friend constexpr bool
    812 	operator==(const expected& __x, const _Up& __v)
    813 	// FIXME: noexcept(noexcept(bool(*__x == __v)))
    814 	{ return __x.has_value() && bool(*__x == __v); }
    815 
    816       template<typename _Er2>
    817 	friend constexpr bool
    818 	operator==(const expected& __x, const unexpected<_Er2>& __e)
    819 	// FIXME: noexcept(noexcept(bool(__x.error() == __e.error())))
    820 	{ return !__x.has_value() && bool(__x.error() == __e.error()); }
    821 
    822       friend constexpr void
    823       swap(expected& __x, expected& __y)
    824       noexcept(noexcept(__x.swap(__y)))
    825       requires requires {__x.swap(__y);}
    826       { __x.swap(__y); }
    827 
    828     private:
    829       template<typename, typename> friend class expected;
    830 
    831       template<typename _Vp>
    832 	constexpr void
    833 	_M_assign_val(_Vp&& __v)
    834 	{
    835 	  if (_M_has_value)
    836 	    _M_val = std::forward<_Vp>(__v);
    837 	  else
    838 	    {
    839 	      __expected::__reinit(__builtin_addressof(_M_val),
    840 				   __builtin_addressof(_M_unex),
    841 				   std::forward<_Vp>(__v));
    842 	      _M_has_value = true;
    843 	    }
    844 	}
    845 
    846       template<typename _Vp>
    847 	constexpr void
    848 	_M_assign_unex(_Vp&& __v)
    849 	{
    850 	  if (_M_has_value)
    851 	    {
    852 	      __expected::__reinit(__builtin_addressof(_M_unex),
    853 				   __builtin_addressof(_M_val),
    854 				   std::forward<_Vp>(__v));
    855 	      _M_has_value = false;
    856 	    }
    857 	  else
    858 	    _M_unex = std::forward<_Vp>(__v);
    859 	}
    860 
    861       // Swap two expected objects when only one has a value.
    862       // Precondition: this->_M_has_value && !__rhs._M_has_value
    863       constexpr void
    864       _M_swap_val_unex(expected& __rhs)
    865       noexcept(__and_v<is_nothrow_move_constructible<_Er>,
    866 		       is_nothrow_move_constructible<_Tp>>)
    867       {
    868 	if constexpr (is_nothrow_move_constructible_v<_Er>)
    869 	  {
    870 	    __expected::_Guard<_Er> __guard(__rhs._M_unex);
    871 	    std::construct_at(__builtin_addressof(__rhs._M_val),
    872 			      std::move(_M_val)); // might throw
    873 	    __rhs._M_has_value = true;
    874 	    std::destroy_at(__builtin_addressof(_M_val));
    875 	    std::construct_at(__builtin_addressof(_M_unex),
    876 			      __guard.release());
    877 	    _M_has_value = false;
    878 	  }
    879 	else
    880 	  {
    881 	    __expected::_Guard<_Tp> __guard(_M_val);
    882 	    std::construct_at(__builtin_addressof(_M_unex),
    883 			      std::move(__rhs._M_unex)); // might throw
    884 	    _M_has_value = false;
    885 	    std::destroy_at(__builtin_addressof(__rhs._M_unex));
    886 	    std::construct_at(__builtin_addressof(__rhs._M_val),
    887 			      __guard.release());
    888 	    __rhs._M_has_value = true;
    889 	  }
    890       }
    891 
    892       union {
    893 	_Tp _M_val;
    894 	_Er _M_unex;
    895       };
    896 
    897       bool _M_has_value;
    898     };
    899 
    900   // Partial specialization for std::expected<cv void, E>
    901   template<typename _Tp, typename _Er> requires is_void_v<_Tp>
    902     class expected<_Tp, _Er>
    903     {
    904       static_assert( __expected::__can_be_unexpected<_Er> );
    905 
    906       template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
    907 	static constexpr bool __cons_from_expected
    908 	  = __or_v<is_constructible<_Unex, expected<_Up, _Err>&>,
    909 		   is_constructible<_Unex, expected<_Up, _Err>>,
    910 		   is_constructible<_Unex, const expected<_Up, _Err>&>,
    911 		   is_constructible<_Unex, const expected<_Up, _Err>>
    912 		  >;
    913 
    914     public:
    915       using value_type = _Tp;
    916       using error_type = _Er;
    917       using unexpected_type = unexpected<_Er>;
    918 
    919       template<typename _Up>
    920 	using rebind = expected<_Up, error_type>;
    921 
    922       constexpr
    923       expected() noexcept
    924       : _M_void(), _M_has_value(true)
    925       { }
    926 
    927       expected(const expected&) = default;
    928 
    929       constexpr
    930       expected(const expected& __x)
    931       noexcept(is_nothrow_copy_constructible_v<_Er>)
    932       requires is_copy_constructible_v<_Er>
    933 	    && (!is_trivially_copy_constructible_v<_Er>)
    934       : _M_void(), _M_has_value(__x._M_has_value)
    935       {
    936 	if (!_M_has_value)
    937 	  std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
    938       }
    939 
    940       expected(expected&&) = default;
    941 
    942       constexpr
    943       expected(expected&& __x)
    944       noexcept(is_nothrow_move_constructible_v<_Er>)
    945       requires is_move_constructible_v<_Er>
    946 	    && (!is_trivially_move_constructible_v<_Er>)
    947       : _M_void(), _M_has_value(__x._M_has_value)
    948       {
    949 	if (!_M_has_value)
    950 	  std::construct_at(__builtin_addressof(_M_unex),
    951 			    std::move(__x)._M_unex);
    952       }
    953 
    954       template<typename _Up, typename _Gr>
    955 	requires is_void_v<_Up>
    956 	      && is_constructible_v<_Er, const _Gr&>
    957 	      && (!__cons_from_expected<_Up, _Gr>)
    958 	constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
    959 	expected(const expected<_Up, _Gr>& __x)
    960 	noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
    961 	: _M_void(), _M_has_value(__x._M_has_value)
    962 	{
    963 	  if (!_M_has_value)
    964 	    std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
    965 	}
    966 
    967       template<typename _Up, typename _Gr>
    968 	requires is_void_v<_Up>
    969 	      && is_constructible_v<_Er, _Gr>
    970 	      && (!__cons_from_expected<_Up, _Gr>)
    971 	constexpr explicit(!is_convertible_v<_Gr, _Er>)
    972 	expected(expected<_Up, _Gr>&& __x)
    973 	noexcept(is_nothrow_constructible_v<_Er, _Gr>)
    974 	: _M_void(), _M_has_value(__x._M_has_value)
    975 	{
    976 	  if (!_M_has_value)
    977 	    std::construct_at(__builtin_addressof(_M_unex),
    978 			      std::move(__x)._M_unex);
    979 	}
    980 
    981       template<typename _Gr = _Er>
    982 	requires is_constructible_v<_Er, const _Gr&>
    983 	constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
    984 	expected(const unexpected<_Gr>& __u)
    985 	noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
    986 	: _M_unex(__u.error()), _M_has_value(false)
    987 	{ }
    988 
    989       template<typename _Gr = _Er>
    990 	requires is_constructible_v<_Er, _Gr>
    991 	constexpr explicit(!is_convertible_v<_Gr, _Er>)
    992 	expected(unexpected<_Gr>&& __u)
    993 	noexcept(is_nothrow_constructible_v<_Er, _Gr>)
    994 	: _M_unex(std::move(__u).error()), _M_has_value(false)
    995 	{ }
    996 
    997       constexpr explicit
    998       expected(in_place_t) noexcept
    999       : expected()
   1000       { }
   1001 
   1002       template<typename... _Args>
   1003 	requires is_constructible_v<_Er, _Args...>
   1004 	constexpr explicit
   1005 	expected(unexpect_t, _Args&&... __args)
   1006 	noexcept(is_nothrow_constructible_v<_Er, _Args...>)
   1007 	: _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
   1008 	{ }
   1009 
   1010       template<typename _Up, typename... _Args>
   1011 	requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
   1012 	constexpr explicit
   1013 	expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
   1014 	noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
   1015 					    _Args...>)
   1016 	: _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
   1017 	{ }
   1018 
   1019       constexpr ~expected() = default;
   1020 
   1021       constexpr ~expected() requires (!is_trivially_destructible_v<_Er>)
   1022       {
   1023 	if (!_M_has_value)
   1024 	  std::destroy_at(__builtin_addressof(_M_unex));
   1025       }
   1026 
   1027       // assignment
   1028 
   1029       expected& operator=(const expected&) = delete;
   1030 
   1031       constexpr expected&
   1032       operator=(const expected& __x)
   1033       noexcept(__and_v<is_nothrow_copy_constructible<_Er>,
   1034 		       is_nothrow_copy_assignable<_Er>>)
   1035       requires is_copy_constructible_v<_Er>
   1036 	    && is_copy_assignable_v<_Er>
   1037       {
   1038 	if (__x._M_has_value)
   1039 	  emplace();
   1040 	else
   1041 	  _M_assign_unex(__x._M_unex);
   1042 	return *this;
   1043       }
   1044 
   1045       constexpr expected&
   1046       operator=(expected&& __x)
   1047       noexcept(__and_v<is_nothrow_move_constructible<_Er>,
   1048 		       is_nothrow_move_assignable<_Er>>)
   1049       requires is_move_constructible_v<_Er>
   1050 	    && is_move_assignable_v<_Er>
   1051       {
   1052 	if (__x._M_has_value)
   1053 	  emplace();
   1054 	else
   1055 	  _M_assign_unex(std::move(__x._M_unex));
   1056 	return *this;
   1057       }
   1058 
   1059       template<typename _Gr>
   1060 	requires is_constructible_v<_Er, const _Gr&>
   1061 	      && is_assignable_v<_Er&, const _Gr&>
   1062 	constexpr expected&
   1063 	operator=(const unexpected<_Gr>& __e)
   1064 	{
   1065 	  _M_assign_unex(__e.error());
   1066 	  return *this;
   1067 	}
   1068 
   1069       template<typename _Gr>
   1070 	requires is_constructible_v<_Er, _Gr>
   1071 	      && is_assignable_v<_Er&, _Gr>
   1072 	constexpr expected&
   1073 	operator=(unexpected<_Gr>&& __e)
   1074 	{
   1075 	  _M_assign_unex(std::move(__e.error()));
   1076 	  return *this;
   1077 	}
   1078 
   1079       // modifiers
   1080 
   1081       constexpr void
   1082       emplace() noexcept
   1083       {
   1084 	if (!_M_has_value)
   1085 	  {
   1086 	    std::destroy_at(__builtin_addressof(_M_unex));
   1087 	    _M_has_value = true;
   1088 	  }
   1089       }
   1090 
   1091       // swap
   1092       constexpr void
   1093       swap(expected& __x)
   1094       noexcept(__and_v<is_nothrow_swappable<_Er&>,
   1095 		       is_nothrow_move_constructible<_Er>>)
   1096       requires is_swappable_v<_Er> && is_move_constructible_v<_Er>
   1097       {
   1098 	if (_M_has_value)
   1099 	  {
   1100 	    if (!__x._M_has_value)
   1101 	      {
   1102 		std::construct_at(__builtin_addressof(_M_unex),
   1103 				  std::move(__x._M_unex)); // might throw
   1104 		std::destroy_at(__builtin_addressof(__x._M_unex));
   1105 		_M_has_value = false;
   1106 		__x._M_has_value = true;
   1107 	      }
   1108 	  }
   1109 	else
   1110 	  {
   1111 	    if (__x._M_has_value)
   1112 	      {
   1113 		std::construct_at(__builtin_addressof(__x._M_unex),
   1114 				  std::move(_M_unex)); // might throw
   1115 		std::destroy_at(__builtin_addressof(_M_unex));
   1116 		_M_has_value = true;
   1117 		__x._M_has_value = false;
   1118 	      }
   1119 	    else
   1120 	      {
   1121 		using std::swap;
   1122 		swap(_M_unex, __x._M_unex);
   1123 	      }
   1124 	  }
   1125       }
   1126 
   1127       // observers
   1128 
   1129       [[nodiscard]]
   1130       constexpr explicit
   1131       operator bool() const noexcept { return _M_has_value; }
   1132 
   1133       [[nodiscard]]
   1134       constexpr bool has_value() const noexcept { return _M_has_value; }
   1135 
   1136       constexpr void
   1137       operator*() const noexcept { __glibcxx_assert(_M_has_value); }
   1138 
   1139       constexpr void
   1140       value() const&
   1141       {
   1142 	if (_M_has_value) [[likely]]
   1143 	  return;
   1144 	_GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
   1145       }
   1146 
   1147       constexpr void
   1148       value() &&
   1149       {
   1150 	if (_M_has_value) [[likely]]
   1151 	  return;
   1152 	_GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex)));
   1153       }
   1154 
   1155       constexpr const _Er&
   1156       error() const & noexcept
   1157       {
   1158 	__glibcxx_assert(!_M_has_value);
   1159 	return _M_unex;
   1160       }
   1161 
   1162       constexpr _Er&
   1163       error() & noexcept
   1164       {
   1165 	__glibcxx_assert(!_M_has_value);
   1166 	return _M_unex;
   1167       }
   1168 
   1169       constexpr const _Er&&
   1170       error() const && noexcept
   1171       {
   1172 	__glibcxx_assert(!_M_has_value);
   1173 	return std::move(_M_unex);
   1174       }
   1175 
   1176       constexpr _Er&&
   1177       error() && noexcept
   1178       {
   1179 	__glibcxx_assert(!_M_has_value);
   1180 	return std::move(_M_unex);
   1181       }
   1182 
   1183       // equality operators
   1184 
   1185       template<typename _Up, typename _Er2>
   1186 	requires is_void_v<_Up>
   1187 	friend constexpr bool
   1188 	operator==(const expected& __x, const expected<_Up, _Er2>& __y)
   1189 	// FIXME: noexcept(noexcept(bool(__x.error() == __y.error())))
   1190 	{
   1191 	  if (__x.has_value())
   1192 	    return __y.has_value();
   1193 	  else
   1194 	    return !__y.has_value() && bool(__x.error() == __y.error());
   1195 	}
   1196 
   1197       template<typename _Er2>
   1198 	friend constexpr bool
   1199 	operator==(const expected& __x, const unexpected<_Er2>& __e)
   1200 	// FIXME: noexcept(noexcept(bool(__x.error() == __e.error())))
   1201 	{ return !__x.has_value() && bool(__x.error() == __e.error()); }
   1202 
   1203       friend constexpr void
   1204       swap(expected& __x, expected& __y)
   1205       noexcept(noexcept(__x.swap(__y)))
   1206       requires requires { __x.swap(__y); }
   1207       { __x.swap(__y); }
   1208 
   1209     private:
   1210       template<typename, typename> friend class expected;
   1211 
   1212       template<typename _Vp>
   1213 	constexpr void
   1214 	_M_assign_unex(_Vp&& __v)
   1215 	{
   1216 	  if (_M_has_value)
   1217 	    {
   1218 	      std::construct_at(__builtin_addressof(_M_unex),
   1219 				std::forward<_Vp>(__v));
   1220 	      _M_has_value = false;
   1221 	    }
   1222 	  else
   1223 	    _M_unex = std::forward<_Vp>(__v);
   1224 	}
   1225 
   1226 
   1227       union {
   1228 	struct { } _M_void;
   1229 	_Er _M_unex;
   1230       };
   1231 
   1232       bool _M_has_value;
   1233     };
   1234   /// @}
   1235 
   1236 _GLIBCXX_END_NAMESPACE_VERSION
   1237 } // namespace std
   1238 
   1239 #endif // C++23
   1240 #endif // _GLIBCXX_EXPECTED
   1241