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  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
constexpr complex< _Tp > operator*(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x times y.
Definition: complex:392
constexpr bool is_swappable_v
is_swappable_v
Definition: type_traits:2789
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:104
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:77
void swap(any &__x, any &__y) noexcept
Exchange the states of two any objects.
Definition: any:429
void unexpected()
ISO C++ entities toplevel namespace is std.