libstdc++
expected
Go to the documentation of this file.
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  {
221  static_assert( is_swappable_v<_Er> );
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)
234  noexcept(noexcept(__x.swap(__y)))
235  requires requires {__x.swap(__y);}
236  { __x.swap(__y); }
237 
238  private:
239  _Er _M_unex;
240  };
241 
242  template<typename _Er> unexpected(_Er) -> unexpected<_Er>;
243 
244 /// @cond undoc
245 namespace __expected
246 {
247  template<typename _Tp>
248  struct _Guard
249  {
250  static_assert( is_nothrow_move_constructible_v<_Tp> );
251 
252  constexpr explicit
253  _Guard(_Tp& __x)
254  : _M_guarded(__builtin_addressof(__x)), _M_tmp(std::move(__x)) // nothrow
255  { std::destroy_at(_M_guarded); }
256 
257  constexpr
258  ~_Guard()
259  {
260  if (_M_guarded) [[unlikely]]
261  std::construct_at(_M_guarded, std::move(_M_tmp));
262  }
263 
264  _Guard(const _Guard&) = delete;
265  _Guard& operator=(const _Guard&) = delete;
266 
267  constexpr _Tp&&
268  release() noexcept
269  {
270  _M_guarded = nullptr;
271  return std::move(_M_tmp);
272  }
273 
274  private:
275  _Tp* _M_guarded;
276  _Tp _M_tmp;
277  };
278 
279  // reinit-expected helper from [expected.object.assign]
280  template<typename _Tp, typename _Up, typename _Vp>
281  constexpr void
282  __reinit(_Tp* __newval, _Up* __oldval, _Vp&& __arg)
283  noexcept(is_nothrow_constructible_v<_Tp, _Vp>)
284  {
285  if constexpr (is_nothrow_constructible_v<_Tp, _Vp>)
286  {
287  std::destroy_at(__oldval);
288  std::construct_at(__newval, std::forward<_Vp>(__arg));
289  }
290  else if constexpr (is_nothrow_move_constructible_v<_Tp>)
291  {
292  _Tp __tmp(std::forward<_Vp>(__arg)); // might throw
293  std::destroy_at(__oldval);
294  std::construct_at(__newval, std::move(__tmp));
295  }
296  else
297  {
298  _Guard<_Up> __guard(*__oldval);
299  std::construct_at(__newval, std::forward<_Vp>(__arg)); // might throw
300  __guard.release();
301  }
302  }
303 }
304 /// @endcond
305 
306  template<typename _Tp, typename _Er>
307  class expected
308  {
309  static_assert( ! is_reference_v<_Tp> );
310  static_assert( ! is_function_v<_Tp> );
311  static_assert( ! is_same_v<remove_cv_t<_Tp>, in_place_t> );
312  static_assert( ! is_same_v<remove_cv_t<_Tp>, unexpect_t> );
313  static_assert( ! __expected::__is_unexpected<remove_cv_t<_Tp>> );
314  static_assert( __expected::__can_be_unexpected<_Er> );
315 
316  template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
317  static constexpr bool __cons_from_expected
318  = __or_v<is_constructible<_Tp, expected<_Up, _Err>&>,
319  is_constructible<_Tp, expected<_Up, _Err>>,
320  is_constructible<_Tp, const expected<_Up, _Err>&>,
321  is_constructible<_Tp, const expected<_Up, _Err>>,
322  is_convertible<expected<_Up, _Err>&, _Tp>,
323  is_convertible<expected<_Up, _Err>, _Tp>,
324  is_convertible<const expected<_Up, _Err>&, _Tp>,
325  is_convertible<const expected<_Up, _Err>, _Tp>,
326  is_constructible<_Unex, expected<_Up, _Err>&>,
327  is_constructible<_Unex, expected<_Up, _Err>>,
328  is_constructible<_Unex, const expected<_Up, _Err>&>,
329  is_constructible<_Unex, const expected<_Up, _Err>>
330  >;
331 
332  template<typename _Up, typename _Err>
333  constexpr static bool __explicit_conv
334  = __or_v<__not_<is_convertible<_Up, _Tp>>,
335  __not_<is_convertible<_Err, _Er>>
336  >;
337 
338  public:
339  using value_type = _Tp;
340  using error_type = _Er;
341  using unexpected_type = unexpected<_Er>;
342 
343  template<typename _Up>
344  using rebind = expected<_Up, error_type>;
345 
346  constexpr
347  expected()
348  noexcept(is_nothrow_default_constructible_v<_Tp>)
349  requires is_default_constructible_v<_Tp>
350  : _M_val(), _M_has_value(true)
351  { }
352 
353  expected(const expected&) = default;
354 
355  constexpr
356  expected(const expected& __x)
357  noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
358  is_nothrow_copy_constructible<_Er>>)
359  requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Er>
360  && (!is_trivially_copy_constructible_v<_Tp>
361  || !is_trivially_copy_constructible_v<_Er>)
362  : _M_invalid(), _M_has_value(__x._M_has_value)
363  {
364  if (_M_has_value)
365  std::construct_at(__builtin_addressof(_M_val), __x._M_val);
366  else
367  std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
368  }
369 
370  expected(expected&&) = default;
371 
372  constexpr
373  expected(expected&& __x)
374  noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
375  is_nothrow_move_constructible<_Er>>)
376  requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Er>
377  && (!is_trivially_move_constructible_v<_Tp>
378  || !is_trivially_move_constructible_v<_Er>)
379  : _M_invalid(), _M_has_value(__x._M_has_value)
380  {
381  if (_M_has_value)
382  std::construct_at(__builtin_addressof(_M_val),
383  std::move(__x)._M_val);
384  else
385  std::construct_at(__builtin_addressof(_M_unex),
386  std::move(__x)._M_unex);
387  }
388 
389  template<typename _Up, typename _Gr>
390  requires is_constructible_v<_Tp, const _Up&>
391  && is_constructible_v<_Er, const _Gr&>
392  && (!__cons_from_expected<_Up, _Gr>)
393  constexpr explicit(__explicit_conv<const _Up&, const _Gr&>)
394  expected(const expected<_Up, _Gr>& __x)
395  noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
396  is_nothrow_constructible<_Er, const _Gr&>>)
397  : _M_invalid(), _M_has_value(__x._M_has_value)
398  {
399  if (_M_has_value)
400  std::construct_at(__builtin_addressof(_M_val), __x._M_val);
401  else
402  std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
403  }
404 
405  template<typename _Up, typename _Gr>
406  requires is_constructible_v<_Tp, _Up>
407  && is_constructible_v<_Er, _Gr>
408  && (!__cons_from_expected<_Up, _Gr>)
409  constexpr explicit(__explicit_conv<_Up, _Gr>)
410  expected(expected<_Up, _Gr>&& __x)
411  noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
412  is_nothrow_constructible<_Er, _Gr>>)
413  : _M_invalid(), _M_has_value(__x._M_has_value)
414  {
415  if (_M_has_value)
416  std::construct_at(__builtin_addressof(_M_val),
417  std::move(__x)._M_val);
418  else
419  std::construct_at(__builtin_addressof(_M_unex),
420  std::move(__x)._M_unex);
421  }
422 
423  template<typename _Up = _Tp>
424  requires (!is_same_v<remove_cvref_t<_Up>, expected>)
425  && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
426  && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
427  && is_constructible_v<_Tp, _Up>
428  constexpr explicit(!is_convertible_v<_Up, _Tp>)
429  expected(_Up&& __v)
430  noexcept(is_nothrow_constructible_v<_Tp, _Up>)
431  : _M_val(std::forward<_Up>(__v)), _M_has_value(true)
432  { }
433 
434  template<typename _Gr = _Er>
435  requires is_constructible_v<_Er, const _Gr&>
436  constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
437  expected(const unexpected<_Gr>& __u)
438  noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
439  : _M_unex(__u.error()), _M_has_value(false)
440  { }
441 
442  template<typename _Gr = _Er>
443  requires is_constructible_v<_Er, _Gr>
444  constexpr explicit(!is_convertible_v<_Gr, _Er>)
445  expected(unexpected<_Gr>&& __u)
446  noexcept(is_nothrow_constructible_v<_Er, _Gr>)
447  : _M_unex(std::move(__u).error()), _M_has_value(false)
448  { }
449 
450  template<typename... _Args>
451  requires is_constructible_v<_Tp, _Args...>
452  constexpr explicit
453  expected(in_place_t, _Args&&... __args)
454  noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
455  : _M_val(std::forward<_Args>(__args)...), _M_has_value(true)
456  { }
457 
458  template<typename _Up, typename... _Args>
459  requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
460  constexpr explicit
461  expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
462  noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
463  _Args...>)
464  : _M_val(__il, std::forward<_Args>(__args)...), _M_has_value(true)
465  { }
466 
467  template<typename... _Args>
468  requires is_constructible_v<_Er, _Args...>
469  constexpr explicit
470  expected(unexpect_t, _Args&&... __args)
471  noexcept(is_nothrow_constructible_v<_Er, _Args...>)
472  : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
473  { }
474 
475  template<typename _Up, typename... _Args>
476  requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
477  constexpr explicit
478  expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
479  noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
480  _Args...>)
481  : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
482  { }
483 
484  constexpr ~expected() = default;
485 
486  constexpr ~expected()
487  requires (!is_trivially_destructible_v<_Tp>)
488  || (!is_trivially_destructible_v<_Er>)
489  {
490  if (_M_has_value)
491  std::destroy_at(__builtin_addressof(_M_val));
492  else
493  std::destroy_at(__builtin_addressof(_M_unex));
494  }
495 
496  // assignment
497 
498  expected& operator=(const expected&) = delete;
499 
500  constexpr expected&
501  operator=(const expected& __x)
502  noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
503  is_nothrow_copy_constructible<_Er>,
504  is_nothrow_copy_assignable<_Tp>,
505  is_nothrow_copy_assignable<_Er>>)
506  requires is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp>
507  && is_copy_assignable_v<_Er> && is_copy_constructible_v<_Er>
508  && (is_nothrow_move_constructible_v<_Tp>
509  || is_nothrow_move_constructible_v<_Er>)
510  {
511  if (__x._M_has_value)
512  this->_M_assign_val(__x._M_val);
513  else
514  this->_M_assign_unex(__x._M_unex);
515  return *this;
516  }
517 
518  constexpr expected&
519  operator=(expected&& __x)
520  noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
521  is_nothrow_move_constructible<_Er>,
522  is_nothrow_move_assignable<_Tp>,
523  is_nothrow_move_assignable<_Er>>)
524  requires is_move_assignable_v<_Tp> && is_move_constructible_v<_Tp>
525  && is_move_assignable_v<_Er> && is_move_constructible_v<_Er>
526  && (is_nothrow_move_constructible_v<_Tp>
527  || is_nothrow_move_constructible_v<_Er>)
528  {
529  if (__x._M_has_value)
530  _M_assign_val(std::move(__x._M_val));
531  else
532  _M_assign_unex(std::move(__x._M_unex));
533  return *this;
534  }
535 
536  template<typename _Up = _Tp>
537  requires (!is_same_v<expected, remove_cvref_t<_Up>>)
538  && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
539  && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up>
540  && (is_nothrow_constructible_v<_Tp, _Up>
541  || is_nothrow_move_constructible_v<_Tp>
542  || is_nothrow_move_constructible_v<_Er>)
543  constexpr expected&
544  operator=(_Up&& __v)
545  {
546  _M_assign_val(std::forward<_Up>(__v));
547  return *this;
548  }
549 
550  template<typename _Gr>
551  requires is_constructible_v<_Er, const _Gr&>
552  && is_assignable_v<_Er&, const _Gr&>
553  && (is_nothrow_constructible_v<_Er, const _Gr&>
554  || is_nothrow_move_constructible_v<_Tp>
555  || is_nothrow_move_constructible_v<_Er>)
556  constexpr expected&
557  operator=(const unexpected<_Gr>& __e)
558  {
559  _M_assign_unex(__e.error());
560  return *this;
561  }
562 
563  template<typename _Gr>
564  requires is_constructible_v<_Er, _Gr>
565  && is_assignable_v<_Er&, _Gr>
566  && (is_nothrow_constructible_v<_Er, _Gr>
567  || is_nothrow_move_constructible_v<_Tp>
568  || is_nothrow_move_constructible_v<_Er>)
569  constexpr expected&
570  operator=(unexpected<_Gr>&& __e)
571  {
572  _M_assign_unex(std::move(__e).error());
573  return *this;
574  }
575 
576  // modifiers
577 
578  template<typename... _Args>
579  requires is_nothrow_constructible_v<_Tp, _Args...>
580  constexpr _Tp&
581  emplace(_Args&&... __args) noexcept
582  {
583  if (_M_has_value)
584  std::destroy_at(__builtin_addressof(_M_val));
585  else
586  {
587  std::destroy_at(__builtin_addressof(_M_unex));
588  _M_has_value = true;
589  }
590  std::construct_at(__builtin_addressof(_M_val),
591  std::forward<_Args>(__args)...);
592  return _M_val;
593  }
594 
595  template<typename _Up, typename... _Args>
596  requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
597  _Args...>
598  constexpr _Tp&
599  emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept
600  {
601  if (_M_has_value)
602  std::destroy_at(__builtin_addressof(_M_val));
603  else
604  {
605  std::destroy_at(__builtin_addressof(_M_unex));
606  _M_has_value = true;
607  }
608  std::construct_at(__builtin_addressof(_M_val),
609  __il, std::forward<_Args>(__args)...);
610  return _M_val;
611  }
612 
613  // swap
614  constexpr void
615  swap(expected& __x)
616  noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
617  is_nothrow_move_constructible<_Er>,
618  is_nothrow_swappable<_Tp&>,
619  is_nothrow_swappable<_Er&>>)
620  requires is_swappable_v<_Tp> && is_swappable_v<_Er>
621  && is_move_constructible_v<_Tp>
622  && is_move_constructible_v<_Er>
623  && (is_nothrow_move_constructible_v<_Tp>
624  || is_nothrow_move_constructible_v<_Er>)
625  {
626  if (_M_has_value)
627  {
628  if (__x._M_has_value)
629  {
630  using std::swap;
631  swap(_M_val, __x._M_val);
632  }
633  else
634  this->_M_swap_val_unex(__x);
635  }
636  else
637  {
638  if (__x._M_has_value)
639  __x._M_swap_val_unex(*this);
640  else
641  {
642  using std::swap;
643  swap(_M_unex, __x._M_unex);
644  }
645  }
646  }
647 
648  // observers
649 
650  [[nodiscard]]
651  constexpr const _Tp*
652  operator->() const noexcept
653  {
654  __glibcxx_assert(_M_has_value);
655  return __builtin_addressof(_M_val);
656  }
657 
658  [[nodiscard]]
659  constexpr _Tp*
660  operator->() noexcept
661  {
662  __glibcxx_assert(_M_has_value);
663  return __builtin_addressof(_M_val);
664  }
665 
666  [[nodiscard]]
667  constexpr const _Tp&
668  operator*() const & noexcept
669  {
670  __glibcxx_assert(_M_has_value);
671  return _M_val;
672  }
673 
674  [[nodiscard]]
675  constexpr _Tp&
676  operator*() & noexcept
677  {
678  __glibcxx_assert(_M_has_value);
679  return _M_val;
680  }
681 
682  [[nodiscard]]
683  constexpr const _Tp&&
684  operator*() const && noexcept
685  {
686  __glibcxx_assert(_M_has_value);
687  return std::move(_M_val);
688  }
689 
690  [[nodiscard]]
691  constexpr _Tp&&
692  operator*() && noexcept
693  {
694  __glibcxx_assert(_M_has_value);
695  return std::move(_M_val);
696  }
697 
698  [[nodiscard]]
699  constexpr explicit
700  operator bool() const noexcept { return _M_has_value; }
701 
702  [[nodiscard]]
703  constexpr bool has_value() const noexcept { return _M_has_value; }
704 
705  constexpr const _Tp&
706  value() const &
707  {
708  if (_M_has_value) [[likely]]
709  return _M_val;
710  _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
711  }
712 
713  constexpr _Tp&
714  value() &
715  {
716  if (_M_has_value) [[likely]]
717  return _M_val;
718  _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_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  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  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  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(__rhs._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  struct { } _M_invalid;
894  _Tp _M_val;
895  _Er _M_unex;
896  };
897 
898  bool _M_has_value;
899  };
900 
901  // Partial specialization for std::expected<cv void, E>
902  template<typename _Tp, typename _Er> requires is_void_v<_Tp>
903  class expected<_Tp, _Er>
904  {
905  static_assert( __expected::__can_be_unexpected<_Er> );
906 
907  template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
908  static constexpr bool __cons_from_expected
909  = __or_v<is_constructible<_Unex, expected<_Up, _Err>&>,
910  is_constructible<_Unex, expected<_Up, _Err>>,
911  is_constructible<_Unex, const expected<_Up, _Err>&>,
912  is_constructible<_Unex, const expected<_Up, _Err>>
913  >;
914 
915  public:
916  using value_type = _Tp;
917  using error_type = _Er;
918  using unexpected_type = unexpected<_Er>;
919 
920  template<typename _Up>
921  using rebind = expected<_Up, error_type>;
922 
923  constexpr
924  expected() noexcept
925  : _M_void(), _M_has_value(true)
926  { }
927 
928  expected(const expected&) = default;
929 
930  constexpr
931  expected(const expected& __x)
932  noexcept(is_nothrow_copy_constructible_v<_Er>)
933  requires is_copy_constructible_v<_Er>
934  && (!is_trivially_copy_constructible_v<_Er>)
935  : _M_void(), _M_has_value(__x._M_has_value)
936  {
937  if (!_M_has_value)
938  std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
939  }
940 
941  expected(expected&&) = default;
942 
943  constexpr
944  expected(expected&& __x)
945  noexcept(is_nothrow_move_constructible_v<_Er>)
946  requires is_move_constructible_v<_Er>
947  && (!is_trivially_move_constructible_v<_Er>)
948  : _M_void(), _M_has_value(__x._M_has_value)
949  {
950  if (!_M_has_value)
951  std::construct_at(__builtin_addressof(_M_unex),
952  std::move(__x)._M_unex);
953  }
954 
955  template<typename _Up, typename _Gr>
956  requires is_void_v<_Up>
957  && is_constructible_v<_Er, const _Gr&>
958  && (!__cons_from_expected<_Up, _Gr>)
959  constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
960  expected(const expected<_Up, _Gr>& __x)
961  noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
962  : _M_void(), _M_has_value(__x._M_has_value)
963  {
964  if (!_M_has_value)
965  std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
966  }
967 
968  template<typename _Up, typename _Gr>
969  requires is_void_v<_Up>
970  && is_constructible_v<_Er, _Gr>
971  && (!__cons_from_expected<_Up, _Gr>)
972  constexpr explicit(!is_convertible_v<_Gr, _Er>)
973  expected(expected<_Up, _Gr>&& __x)
974  noexcept(is_nothrow_constructible_v<_Er, _Gr>)
975  : _M_void(), _M_has_value(__x._M_has_value)
976  {
977  if (!_M_has_value)
978  std::construct_at(__builtin_addressof(_M_unex),
979  std::move(__x)._M_unex);
980  }
981 
982  template<typename _Gr = _Er>
983  requires is_constructible_v<_Er, const _Gr&>
984  constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
985  expected(const unexpected<_Gr>& __u)
986  noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
987  : _M_unex(__u.error()), _M_has_value(false)
988  { }
989 
990  template<typename _Gr = _Er>
991  requires is_constructible_v<_Er, _Gr>
992  constexpr explicit(!is_convertible_v<_Gr, _Er>)
993  expected(unexpected<_Gr>&& __u)
994  noexcept(is_nothrow_constructible_v<_Er, _Gr>)
995  : _M_unex(std::move(__u).error()), _M_has_value(false)
996  { }
997 
998  template<typename... _Args>
999  constexpr explicit
1000  expected(in_place_t) noexcept
1001  : expected()
1002  { }
1003 
1004  template<typename... _Args>
1005  requires is_constructible_v<_Er, _Args...>
1006  constexpr explicit
1007  expected(unexpect_t, _Args&&... __args)
1008  noexcept(is_nothrow_constructible_v<_Er, _Args...>)
1009  : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
1010  { }
1011 
1012  template<typename _Up, typename... _Args>
1013  requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
1014  constexpr explicit
1015  expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
1016  noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
1017  _Args...>)
1018  : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
1019  { }
1020 
1021  constexpr ~expected() = default;
1022 
1023  constexpr ~expected() requires (!is_trivially_destructible_v<_Er>)
1024  {
1025  if (!_M_has_value)
1026  std::destroy_at(__builtin_addressof(_M_unex));
1027  }
1028 
1029  // assignment
1030 
1031  expected& operator=(const expected&) = delete;
1032 
1033  constexpr expected&
1034  operator=(const expected& __x)
1035  noexcept(__and_v<is_nothrow_copy_constructible<_Er>,
1036  is_nothrow_copy_assignable<_Er>>)
1037  requires is_copy_constructible_v<_Er>
1038  && is_copy_assignable_v<_Er>
1039  {
1040  if (__x._M_has_value)
1041  emplace();
1042  else
1043  _M_assign_unex(__x._M_unex);
1044  return *this;
1045  }
1046 
1047  constexpr expected&
1048  operator=(expected&& __x)
1049  noexcept(__and_v<is_nothrow_move_constructible<_Er>,
1050  is_nothrow_move_assignable<_Er>>)
1051  requires is_move_constructible_v<_Er>
1052  && is_move_assignable_v<_Er>
1053  {
1054  if (__x._M_has_value)
1055  emplace();
1056  else
1057  _M_assign_unex(std::move(__x._M_unex));
1058  return *this;
1059  }
1060 
1061  template<typename _Gr>
1062  requires is_constructible_v<_Er, const _Gr&>
1063  && is_assignable_v<_Er&, const _Gr&>
1064  constexpr expected&
1065  operator=(const unexpected<_Gr>& __e)
1066  {
1067  _M_assign_unex(__e.error());
1068  return *this;
1069  }
1070 
1071  template<typename _Gr>
1072  requires is_constructible_v<_Er, _Gr>
1073  && is_assignable_v<_Er&, _Gr>
1074  constexpr expected&
1075  operator=(unexpected<_Gr>&& __e)
1076  {
1077  _M_assign_unex(std::move(__e.error()));
1078  return *this;
1079  }
1080 
1081  // modifiers
1082 
1083  constexpr void
1084  emplace() noexcept
1085  {
1086  if (!_M_has_value)
1087  {
1088  std::destroy_at(__builtin_addressof(_M_unex));
1089  _M_has_value = true;
1090  }
1091  }
1092 
1093  // swap
1094  constexpr void
1095  swap(expected& __x)
1096  noexcept(__and_v<is_nothrow_swappable<_Er&>,
1097  is_nothrow_move_constructible<_Er>>)
1098  requires is_swappable_v<_Er> && is_move_constructible_v<_Er>
1099  {
1100  if (_M_has_value)
1101  {
1102  if (!__x._M_has_value)
1103  {
1104  std::construct_at(__builtin_addressof(_M_unex),
1105  std::move(__x._M_unex)); // might throw
1106  std::destroy_at(__builtin_addressof(__x._M_unex));
1107  _M_has_value = false;
1108  __x._M_has_value = true;
1109  }
1110  }
1111  else
1112  {
1113  if (__x._M_has_value)
1114  {
1115  std::construct_at(__builtin_addressof(__x._M_unex),
1116  std::move(_M_unex)); // might throw
1117  std::destroy_at(__builtin_addressof(_M_unex));
1118  _M_has_value = true;
1119  __x._M_has_value = false;
1120  }
1121  else
1122  {
1123  using std::swap;
1124  swap(_M_unex, __x._M_unex);
1125  }
1126  }
1127  }
1128 
1129  // observers
1130 
1131  [[nodiscard]]
1132  constexpr explicit
1133  operator bool() const noexcept { return _M_has_value; }
1134 
1135  [[nodiscard]]
1136  constexpr bool has_value() const noexcept { return _M_has_value; }
1137 
1138  constexpr void
1139  operator*() const noexcept { __glibcxx_assert(_M_has_value); }
1140 
1141  constexpr void
1142  value() const&
1143  {
1144  if (_M_has_value) [[likely]]
1145  return;
1146  _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
1147  }
1148 
1149  constexpr void
1150  value() &&
1151  {
1152  if (_M_has_value) [[likely]]
1153  return;
1154  _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex)));
1155  }
1156 
1157  constexpr const _Er&
1158  error() const & noexcept
1159  {
1160  __glibcxx_assert(!_M_has_value);
1161  return _M_unex;
1162  }
1163 
1164  constexpr _Er&
1165  error() & noexcept
1166  {
1167  __glibcxx_assert(!_M_has_value);
1168  return _M_unex;
1169  }
1170 
1171  constexpr const _Er&&
1172  error() const && noexcept
1173  {
1174  __glibcxx_assert(!_M_has_value);
1175  return std::move(_M_unex);
1176  }
1177 
1178  constexpr _Er&&
1179  error() && noexcept
1180  {
1181  __glibcxx_assert(!_M_has_value);
1182  return std::move(_M_unex);
1183  }
1184 
1185  // equality operators
1186 
1187  template<typename _Up, typename _Er2>
1188  requires is_void_v<_Up>
1189  friend constexpr bool
1190  operator==(const expected& __x, const expected<_Up, _Er2>& __y)
1191  noexcept(noexcept(bool(__x.error() == __y.error())))
1192  {
1193  if (__x.has_value())
1194  return __y.has_value();
1195  else
1196  return !__y.has_value() && bool(__x.error() == __y.error());
1197  }
1198 
1199  template<typename _Er2>
1200  friend constexpr bool
1201  operator==(const expected& __x, const unexpected<_Er2>& __e)
1202  noexcept(noexcept(bool(__x.error() == __e.error())))
1203  { return !__x.has_value() && bool(__x.error() == __e.error()); }
1204 
1205  friend constexpr void
1206  swap(expected& __x, expected& __y)
1207  noexcept(noexcept(__x.swap(__y)))
1208  requires requires { __x.swap(__y); }
1209  { __x.swap(__y); }
1210 
1211  private:
1212  template<typename, typename> friend class expected;
1213 
1214  template<typename _Vp>
1215  constexpr void
1216  _M_assign_unex(_Vp&& __v)
1217  {
1218  if (_M_has_value)
1219  {
1220  std::construct_at(__builtin_addressof(_M_unex),
1221  std::forward<_Vp>(__v));
1222  _M_has_value = false;
1223  }
1224  else
1225  _M_unex = std::forward<_Vp>(__v);
1226  }
1227 
1228 
1229  union {
1230  struct { } _M_void;
1231  _Er _M_unex;
1232  };
1233 
1234  bool _M_has_value;
1235  };
1236  /// @}
1237 
1238 _GLIBCXX_END_NAMESPACE_VERSION
1239 } // namespace std
1240 
1241 #endif // C++23
1242 #endif // _GLIBCXX_EXPECTED