xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/std/expected (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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
41namespace 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
142namespace __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
244namespace __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