General Utility Library for C++14  2.11
expected.h
Go to the documentation of this file.
1 
25 #ifndef GUL14_EXPECTED_H_
26 #define GUL14_EXPECTED_H_
27 
28 #include <cassert>
29 #include <exception>
30 #include <functional>
31 #include <type_traits>
32 #include <utility>
33 
34 #include "gul14/traits.h"
35 #include "gul14/utility.h"
36 
37 namespace gul14 {
38 
54 template <typename E>
56 
92 template <typename T, typename E>
93 class expected;
94 
100 template <typename E>
102 
104 
105 #if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
106 #define GUL14_EXPECTED_EXCEPTIONS_ENABLED
107 #endif
108 
109 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__))
110 #define GUL14_EXPECTED_GCC54
111 #endif
112 
113 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__))
114 #define GUL14_EXPECTED_GCC55
115 #endif
116 
117 #if (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
118 #ifndef GUL14_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
119 #define GUL14_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
120 namespace detail {
121 template <class T>
122 struct is_trivially_copy_constructible
123  : std::is_trivially_copy_constructible<T> {};
124 #ifdef _GLIBCXX_VECTOR
125 template <class T, class A>
126 struct is_trivially_copy_constructible<std::vector<T, A>> : std::false_type {};
127 #endif
128 } // namespace detail
129 #endif
130 
131 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
132  gul14::detail::is_trivially_copy_constructible<T>
133 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
134  std::is_trivially_copy_assignable<T>
135 #define GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
136  std::is_trivially_destructible<T>
137 #else
138 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
139  std::is_trivially_copy_constructible<T>
140 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
141  std::is_trivially_copy_assignable<T>
142 #define GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
143  std::is_trivially_destructible<T>
144 #endif
145 
146 template <class T, class E> class expected;
147 
148 template <class E>
149 class unexpected
150 {
151 public:
152  static_assert(!std::is_same<E, void>::value, "E must not be void");
153 
154  unexpected() = delete;
155  constexpr explicit unexpected(const E &e) : m_val(e) {}
156 
157  constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {}
158 
159  template <class... Args, typename std::enable_if<std::is_constructible<
160  E, Args &&...>::value>::type * = nullptr>
161  constexpr explicit unexpected(Args &&...args)
162  : m_val(std::forward<Args>(args)...) {}
163  template <
164  class U, class... Args,
165  typename std::enable_if<std::is_constructible<
166  E, std::initializer_list<U> &, Args &&...>::value>::type * = nullptr>
167  constexpr explicit unexpected(std::initializer_list<U> l, Args &&...args)
168  : m_val(l, std::forward<Args>(args)...) {}
169 
170  constexpr const E &value() const & { return m_val; }
171  constexpr E &value() & { return m_val; }
172  constexpr E &&value() && { return std::move(m_val); }
173  constexpr const E &&value() const && { return std::move(m_val); }
174 
175 private:
176  E m_val;
177 };
178 
179 #ifdef __cpp_deduction_guides
180 template <class E> unexpected(E) -> unexpected<E>;
181 #endif
182 
183 template <class E>
184 constexpr bool operator==(const unexpected<E> &lhs, const unexpected<E> &rhs) {
185  return lhs.value() == rhs.value();
186 }
187 template <class E>
188 constexpr bool operator!=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
189  return lhs.value() != rhs.value();
190 }
191 template <class E>
192 constexpr bool operator<(const unexpected<E> &lhs, const unexpected<E> &rhs) {
193  return lhs.value() < rhs.value();
194 }
195 template <class E>
196 constexpr bool operator<=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
197  return lhs.value() <= rhs.value();
198 }
199 template <class E>
200 constexpr bool operator>(const unexpected<E> &lhs, const unexpected<E> &rhs) {
201  return lhs.value() > rhs.value();
202 }
203 template <class E>
204 constexpr bool operator>=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
205  return lhs.value() >= rhs.value();
206 }
207 
208 template <class E>
209 unexpected<typename std::decay<E>::type> make_unexpected(E &&e) {
210  return unexpected<typename std::decay<E>::type>(std::forward<E>(e));
211 }
212 
213 struct unexpect_t {
214  unexpect_t() = default;
215 };
216 static constexpr unexpect_t unexpect{};
217 
218 namespace detail {
219 template <typename E>
220 [[noreturn]] constexpr void throw_exception(E &&e) {
221 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
222  throw std::forward<E>(e);
223 #else
224  (void)e;
225 #ifdef _MSC_VER
226  __assume(0);
227 #else
228  __builtin_unreachable();
229 #endif
230 #endif
231 }
232 
233 #ifndef GUL14_TRAITS_MUTEX
234 #define GUL14_TRAITS_MUTEX
235 // C++14-style aliases for brevity
236 template <class T> using remove_const_t = typename std::remove_const<T>::type;
237 template <class T>
238 using remove_reference_t = typename std::remove_reference<T>::type;
239 template <class T> using decay_t = typename std::decay<T>::type;
240 template <bool E, class T = void>
241 using enable_if_t = typename std::enable_if<E, T>::type;
242 template <bool B, class T, class F>
243 using conditional_t = typename std::conditional<B, T, F>::type;
244 
245 // std::conjunction from C++17
246 template <class...> struct conjunction : std::true_type {};
247 template <class B> struct conjunction<B> : B {};
248 template <class B, class... Bs>
249 struct conjunction<B, Bs...>
250  : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
251 
252 // https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
253 namespace swap_adl_tests {
254 // if swap ADL finds this then it would call std::swap otherwise (same signature)
255 struct tag {};
256 
257 template <class T> tag swap(T &, T &);
258 template <class T, std::size_t N> tag swap(T (&a)[N], T (&b)[N]);
259 
260 // helper functions to test if an unqualified swap is possible, and if it
261 // becomes std::swap
262 template <class, class> std::false_type can_swap(...) noexcept(false);
263 template <class T, class U,
264  class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>
265 std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T &>(),
266  std::declval<U &>())));
267 
268 template <class, class> std::false_type uses_std(...);
269 template <class T, class U>
270 std::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag>
271 uses_std(int);
272 
273 template <class T>
274 struct is_std_swap_noexcept
275  : std::integral_constant<bool,
276  std::is_nothrow_move_constructible<T>::value &&
277  std::is_nothrow_move_assignable<T>::value> {};
278 
279 template <class T, std::size_t N>
280 struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
281 
282 template <class T, class U>
283 struct is_adl_swap_noexcept
284  : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
285 } // namespace swap_adl_tests
286 
287 template <class T, class U = T>
288 struct is_swappable
289  : std::integral_constant<
290  bool,
291  decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
292  (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
293  (std::is_move_assignable<T>::value &&
294  std::is_move_constructible<T>::value))> {};
295 
296 template <class T, std::size_t N>
297 struct is_swappable<T[N], T[N]>
298  : std::integral_constant<
299  bool,
300  decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
301  (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(
302  0))::value ||
303  is_swappable<T, T>::value)> {};
304 
305 template <class T, class U = T>
306 struct is_nothrow_swappable
307  : std::integral_constant<
308  bool,
309  is_swappable<T, U>::value &&
310  ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
311  detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
312  (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
313  detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
314 #endif
315 
316 // Trait for checking if a type is a gul14::expected
317 template <class T> struct is_expected_impl : std::false_type {};
318 template <class T, class E>
319 struct is_expected_impl<expected<T, E>> : std::true_type {};
320 template <class T> using is_expected = is_expected_impl<decay_t<T>>;
321 
322 template <class T, class E, class U>
323 using expected_enable_forward_value = detail::enable_if_t<
324  std::is_constructible<T, U &&>::value &&
325  !std::is_same<detail::decay_t<U>, in_place_t>::value &&
326  !std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
327  !std::is_same<unexpected<E>, detail::decay_t<U>>::value>;
328 
329 template <class T, class E, class U, class G, class UR, class GR>
330 using expected_enable_from_other = detail::enable_if_t<
331  std::is_constructible<T, UR>::value &&
332  std::is_constructible<E, GR>::value &&
333  !std::is_constructible<T, expected<U, G> &>::value &&
334  !std::is_constructible<T, expected<U, G> &&>::value &&
335  !std::is_constructible<T, const expected<U, G> &>::value &&
336  !std::is_constructible<T, const expected<U, G> &&>::value &&
337  !std::is_convertible<expected<U, G> &, T>::value &&
338  !std::is_convertible<expected<U, G> &&, T>::value &&
339  !std::is_convertible<const expected<U, G> &, T>::value &&
340  !std::is_convertible<const expected<U, G> &&, T>::value>;
341 
342 template <class T, class U>
343 using is_void_or = conditional_t<std::is_void<T>::value, std::true_type, U>;
344 
345 template <class T>
346 using is_copy_constructible_or_void =
347  is_void_or<T, std::is_copy_constructible<T>>;
348 
349 template <class T>
350 using is_move_constructible_or_void =
351  is_void_or<T, std::is_move_constructible<T>>;
352 
353 template <class T>
354 using is_copy_assignable_or_void = is_void_or<T, std::is_copy_assignable<T>>;
355 
356 template <class T>
357 using is_move_assignable_or_void = is_void_or<T, std::is_move_assignable<T>>;
358 
359 struct no_init_t {};
360 static constexpr no_init_t no_init{};
361 
362 // Implements the storage of the values, and ensures that the destructor is
363 // trivial if it can be.
364 //
365 // This specialization is for where neither `T` or `E` is trivially
366 // destructible, so the destructors must be called on destruction of the
367 // `expected`
368 template <class T, class E, bool = std::is_trivially_destructible<T>::value,
369  bool = std::is_trivially_destructible<E>::value>
370 struct expected_storage_base {
371  constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
372  constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
373 
374  template <class... Args,
375  detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
376  nullptr>
377  constexpr expected_storage_base(in_place_t, Args &&...args)
378  : m_val(std::forward<Args>(args)...), m_has_val(true) {}
379 
380  template <class U, class... Args,
381  detail::enable_if_t<std::is_constructible<
382  T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
383  constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
384  Args &&...args)
385  : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
386  template <class... Args,
387  detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
388  nullptr>
389  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
390  : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
391 
392  template <class U, class... Args,
393  detail::enable_if_t<std::is_constructible<
394  E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
395  constexpr explicit expected_storage_base(unexpect_t,
396  std::initializer_list<U> il,
397  Args &&...args)
398  : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
399 
400  ~expected_storage_base() {
401  if (m_has_val) {
402  m_val.~T();
403  } else {
404  m_unexpect.~unexpected<E>();
405  }
406  }
407  union {
408  T m_val;
409  unexpected<E> m_unexpect;
410  char m_no_init;
411  };
412  bool m_has_val;
413 };
414 
415 // This specialization is for when both `T` and `E` are trivially-destructible,
416 // so the destructor of the `expected` can be trivial.
417 template <class T, class E> struct expected_storage_base<T, E, true, true> {
418  constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
419  constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
420 
421  template <class... Args,
422  detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
423  nullptr>
424  constexpr expected_storage_base(in_place_t, Args &&...args)
425  : m_val(std::forward<Args>(args)...), m_has_val(true) {}
426 
427  template <class U, class... Args,
428  detail::enable_if_t<std::is_constructible<
429  T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
430  constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
431  Args &&...args)
432  : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
433  template <class... Args,
434  detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
435  nullptr>
436  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
437  : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
438 
439  template <class U, class... Args,
440  detail::enable_if_t<std::is_constructible<
441  E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
442  constexpr explicit expected_storage_base(unexpect_t,
443  std::initializer_list<U> il,
444  Args &&...args)
445  : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
446 
447  ~expected_storage_base() = default;
448  union {
449  T m_val;
450  unexpected<E> m_unexpect;
451  char m_no_init;
452  };
453  bool m_has_val;
454 };
455 
456 // T is trivial, E is not.
457 template <class T, class E> struct expected_storage_base<T, E, true, false> {
458  constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
459  constexpr expected_storage_base(no_init_t)
460  : m_no_init(), m_has_val(false) {}
461 
462  template <class... Args,
463  detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
464  nullptr>
465  constexpr expected_storage_base(in_place_t, Args &&...args)
466  : m_val(std::forward<Args>(args)...), m_has_val(true) {}
467 
468  template <class U, class... Args,
469  detail::enable_if_t<std::is_constructible<
470  T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
471  constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
472  Args &&...args)
473  : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
474  template <class... Args,
475  detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
476  nullptr>
477  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
478  : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
479 
480  template <class U, class... Args,
481  detail::enable_if_t<std::is_constructible<
482  E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
483  constexpr explicit expected_storage_base(unexpect_t,
484  std::initializer_list<U> il,
485  Args &&...args)
486  : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
487 
488  ~expected_storage_base() {
489  if (!m_has_val) {
490  m_unexpect.~unexpected<E>();
491  }
492  }
493 
494  union {
495  T m_val;
496  unexpected<E> m_unexpect;
497  char m_no_init;
498  };
499  bool m_has_val;
500 };
501 
502 // E is trivial, T is not.
503 template <class T, class E> struct expected_storage_base<T, E, false, true> {
504  constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
505  constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
506 
507  template <class... Args,
508  detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
509  nullptr>
510  constexpr expected_storage_base(in_place_t, Args &&...args)
511  : m_val(std::forward<Args>(args)...), m_has_val(true) {}
512 
513  template <class U, class... Args,
514  detail::enable_if_t<std::is_constructible<
515  T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
516  constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
517  Args &&...args)
518  : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
519  template <class... Args,
520  detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
521  nullptr>
522  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
523  : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
524 
525  template <class U, class... Args,
526  detail::enable_if_t<std::is_constructible<
527  E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
528  constexpr explicit expected_storage_base(unexpect_t,
529  std::initializer_list<U> il,
530  Args &&...args)
531  : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
532 
533  ~expected_storage_base() {
534  if (m_has_val) {
535  m_val.~T();
536  }
537  }
538  union {
539  T m_val;
540  unexpected<E> m_unexpect;
541  char m_no_init;
542  };
543  bool m_has_val;
544 };
545 
546 // `T` is `void`, `E` is trivially-destructible
547 template <class E> struct expected_storage_base<void, E, false, true> {
548  #if __GNUC__ <= 5
549  //no constexpr for GCC 4/5 bug
550  #else
551  constexpr
552  #endif
553  expected_storage_base() : m_has_val(true) {}
554 
555  constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {}
556 
557  constexpr expected_storage_base(in_place_t) : m_has_val(true) {}
558 
559  template <class... Args,
560  detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
561  nullptr>
562  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
563  : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
564 
565  template <class U, class... Args,
566  detail::enable_if_t<std::is_constructible<
567  E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
568  constexpr explicit expected_storage_base(unexpect_t,
569  std::initializer_list<U> il,
570  Args &&...args)
571  : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
572 
573  ~expected_storage_base() = default;
574  struct dummy {};
575  union {
576  unexpected<E> m_unexpect;
577  dummy m_val;
578  };
579  bool m_has_val;
580 };
581 
582 // `T` is `void`, `E` is not trivially-destructible
583 template <class E> struct expected_storage_base<void, E, false, false> {
584  constexpr expected_storage_base() : m_dummy(), m_has_val(true) {}
585  constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {}
586 
587  constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {}
588 
589  template <class... Args,
590  detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
591  nullptr>
592  constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
593  : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
594 
595  template <class U, class... Args,
596  detail::enable_if_t<std::is_constructible<
597  E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
598  constexpr explicit expected_storage_base(unexpect_t,
599  std::initializer_list<U> il,
600  Args &&...args)
601  : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
602 
603  ~expected_storage_base() {
604  if (!m_has_val) {
605  m_unexpect.~unexpected<E>();
606  }
607  }
608 
609  union {
610  unexpected<E> m_unexpect;
611  char m_dummy;
612  };
613  bool m_has_val;
614 };
615 
616 // This base class provides some handy member functions which can be used in
617 // further derived classes
618 template <class T, class E>
619 struct expected_operations_base : expected_storage_base<T, E> {
620  using expected_storage_base<T, E>::expected_storage_base;
621 
622  template <class... Args> void construct(Args &&...args) noexcept {
623  new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
624  this->m_has_val = true;
625  }
626 
627  template <class Rhs> void construct_with(Rhs &&rhs) noexcept {
628  new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
629  this->m_has_val = true;
630  }
631 
632  template <class... Args> void construct_error(Args &&...args) noexcept {
633  new (std::addressof(this->m_unexpect))
634  unexpected<E>(std::forward<Args>(args)...);
635  this->m_has_val = false;
636  }
637 
638 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
639 
640  // These assign overloads ensure that the most efficient assignment
641  // implementation is used while maintaining the strong exception guarantee.
642  // The problematic case is where rhs has a value, but *this does not.
643  //
644  // This overload handles the case where we can just copy-construct `T`
645  // directly into place without throwing.
646  template <class U = T,
647  detail::enable_if_t<std::is_nothrow_copy_constructible<U>::value>
648  * = nullptr>
649  void assign(const expected_operations_base &rhs) noexcept {
650  if (!this->m_has_val && rhs.m_has_val) {
651  geterr().~unexpected<E>();
652  construct(rhs.get());
653  } else {
654  assign_common(rhs);
655  }
656  }
657 
658  // This overload handles the case where we can attempt to create a copy of
659  // `T`, then no-throw move it into place if the copy was successful.
660  template <class U = T,
661  detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
662  std::is_nothrow_move_constructible<U>::value>
663  * = nullptr>
664  void assign(const expected_operations_base &rhs) noexcept {
665  if (!this->m_has_val && rhs.m_has_val) {
666  T tmp = rhs.get();
667  geterr().~unexpected<E>();
668  construct(std::move(tmp));
669  } else {
670  assign_common(rhs);
671  }
672  }
673 
674  // This overload is the worst-case, where we have to move-construct the
675  // unexpected value into temporary storage, then try to copy the T into place.
676  // If the construction succeeds, then everything is fine, but if it throws,
677  // then we move the old unexpected value back into place before rethrowing the
678  // exception.
679  template <class U = T,
680  detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
681  !std::is_nothrow_move_constructible<U>::value>
682  * = nullptr>
683  void assign(const expected_operations_base &rhs) {
684  if (!this->m_has_val && rhs.m_has_val) {
685  auto tmp = std::move(geterr());
686  geterr().~unexpected<E>();
687 
688 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
689  try {
690  construct(rhs.get());
691  } catch (...) {
692  geterr() = std::move(tmp);
693  throw;
694  }
695 #else
696  construct(rhs.get());
697 #endif
698  } else {
699  assign_common(rhs);
700  }
701  }
702 
703  // These overloads do the same as above, but for rvalues
704  template <class U = T,
705  detail::enable_if_t<std::is_nothrow_move_constructible<U>::value>
706  * = nullptr>
707  void assign(expected_operations_base &&rhs) noexcept {
708  if (!this->m_has_val && rhs.m_has_val) {
709  geterr().~unexpected<E>();
710  construct(std::move(rhs).get());
711  } else {
712  assign_common(std::move(rhs));
713  }
714  }
715 
716  template <class U = T,
717  detail::enable_if_t<!std::is_nothrow_move_constructible<U>::value>
718  * = nullptr>
719  void assign(expected_operations_base &&rhs) {
720  if (!this->m_has_val && rhs.m_has_val) {
721  auto tmp = std::move(geterr());
722  geterr().~unexpected<E>();
723 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
724  try {
725  construct(std::move(rhs).get());
726  } catch (...) {
727  geterr() = std::move(tmp);
728  throw;
729  }
730 #else
731  construct(std::move(rhs).get());
732 #endif
733  } else {
734  assign_common(std::move(rhs));
735  }
736  }
737 
738 #else
739 
740  // If exceptions are disabled then we can just copy-construct
741  void assign(const expected_operations_base &rhs) noexcept {
742  if (!this->m_has_val && rhs.m_has_val) {
743  geterr().~unexpected<E>();
744  construct(rhs.get());
745  } else {
746  assign_common(rhs);
747  }
748  }
749 
750  void assign(expected_operations_base &&rhs) noexcept {
751  if (!this->m_has_val && rhs.m_has_val) {
752  geterr().~unexpected<E>();
753  construct(std::move(rhs).get());
754  } else {
755  assign_common(std::move(rhs));
756  }
757  }
758 
759 #endif
760 
761  // The common part of move/copy assigning
762  template <class Rhs> void assign_common(Rhs &&rhs) {
763  if (this->m_has_val) {
764  if (rhs.m_has_val) {
765  get() = std::forward<Rhs>(rhs).get();
766  } else {
767  destroy_val();
768  construct_error(std::forward<Rhs>(rhs).geterr());
769  }
770  } else {
771  if (!rhs.m_has_val) {
772  geterr() = std::forward<Rhs>(rhs).geterr();
773  }
774  }
775  }
776 
777  bool has_value() const { return this->m_has_val; }
778 
779  constexpr T &get() & { return this->m_val; }
780  constexpr const T &get() const & { return this->m_val; }
781  constexpr T &&get() && { return std::move(this->m_val); }
782  constexpr const T &&get() const && { return std::move(this->m_val); }
783 
784  constexpr unexpected<E> &geterr() & {
785  return this->m_unexpect;
786  }
787  constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }
788  constexpr unexpected<E> &&geterr() && {
789  return std::move(this->m_unexpect);
790  }
791  constexpr const unexpected<E> &&geterr() const && {
792  return std::move(this->m_unexpect);
793  }
794 
795  constexpr void destroy_val() { get().~T(); }
796 };
797 
798 // This base class provides some handy member functions which can be used in
799 // further derived classes
800 template <class E>
801 struct expected_operations_base<void, E> : expected_storage_base<void, E> {
802  using expected_storage_base<void, E>::expected_storage_base;
803 
804  template <class... Args> void construct() noexcept { this->m_has_val = true; }
805 
806  // This function doesn't use its argument, but needs it so that code in
807  // levels above this can work independently of whether T is void
808  template <class Rhs> void construct_with(Rhs &&) noexcept {
809  this->m_has_val = true;
810  }
811 
812  template <class... Args> void construct_error(Args &&...args) noexcept {
813  new (std::addressof(this->m_unexpect))
814  unexpected<E>(std::forward<Args>(args)...);
815  this->m_has_val = false;
816  }
817 
818  template <class Rhs> void assign(Rhs &&rhs) noexcept {
819  if (!this->m_has_val) {
820  if (rhs.m_has_val) {
821  geterr().~unexpected<E>();
822  construct();
823  } else {
824  geterr() = std::forward<Rhs>(rhs).geterr();
825  }
826  } else {
827  if (!rhs.m_has_val) {
828  construct_error(std::forward<Rhs>(rhs).geterr());
829  }
830  }
831  }
832 
833  bool has_value() const { return this->m_has_val; }
834 
835  constexpr unexpected<E> &geterr() & {
836  return this->m_unexpect;
837  }
838  constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }
839  constexpr unexpected<E> &&geterr() && {
840  return std::move(this->m_unexpect);
841  }
842  constexpr const unexpected<E> &&geterr() const && {
843  return std::move(this->m_unexpect);
844  }
845 
846  constexpr void destroy_val() {
847  // no-op
848  }
849 };
850 
851 // This class manages conditionally having a trivial copy constructor
852 // This specialization is for when T and E are trivially copy constructible
853 template <class T, class E,
854  bool = is_void_or<T, GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::
855  value &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>
856 struct expected_copy_base : expected_operations_base<T, E> {
857  using expected_operations_base<T, E>::expected_operations_base;
858 };
859 
860 // This specialization is for when T or E are not trivially copy constructible
861 template <class T, class E>
862 struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
863  using expected_operations_base<T, E>::expected_operations_base;
864 
865  expected_copy_base() = default;
866  expected_copy_base(const expected_copy_base &rhs)
867  : expected_operations_base<T, E>(no_init) {
868  if (rhs.has_value()) {
869  this->construct_with(rhs);
870  } else {
871  this->construct_error(rhs.geterr());
872  }
873  }
874 
875  expected_copy_base(expected_copy_base &&rhs) = default;
876  expected_copy_base &operator=(const expected_copy_base &rhs) = default;
877  expected_copy_base &operator=(expected_copy_base &&rhs) = default;
878 };
879 
880 // This class manages conditionally having a trivial move constructor
881 template <class T, class E,
882  bool = is_void_or<T, std::is_trivially_move_constructible<T>>::value
883  &&std::is_trivially_move_constructible<E>::value>
884 struct expected_move_base : expected_copy_base<T, E> {
885  using expected_copy_base<T, E>::expected_copy_base;
886 };
887 
888 template <class T, class E>
889 struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
890  using expected_copy_base<T, E>::expected_copy_base;
891 
892  expected_move_base() = default;
893  expected_move_base(const expected_move_base &rhs) = default;
894 
895  expected_move_base(expected_move_base &&rhs) noexcept(
896  std::is_nothrow_move_constructible<T>::value)
897  : expected_copy_base<T, E>(no_init) {
898  if (rhs.has_value()) {
899  this->construct_with(std::move(rhs));
900  } else {
901  this->construct_error(std::move(rhs.geterr()));
902  }
903  }
904  expected_move_base &operator=(const expected_move_base &rhs) = default;
905  expected_move_base &operator=(expected_move_base &&rhs) = default;
906 };
907 
908 // This class manages conditionally having a trivial copy assignment operator
909 template <class T, class E,
910  bool = is_void_or<
911  T, conjunction<GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T),
912  GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T),
913  GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value
914  &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value
915  &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value
916  &&GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>
917 struct expected_copy_assign_base : expected_move_base<T, E> {
918  using expected_move_base<T, E>::expected_move_base;
919 };
920 
921 template <class T, class E>
922 struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
923  using expected_move_base<T, E>::expected_move_base;
924 
925  expected_copy_assign_base() = default;
926  expected_copy_assign_base(const expected_copy_assign_base &rhs) = default;
927 
928  expected_copy_assign_base(expected_copy_assign_base &&rhs) = default;
929  expected_copy_assign_base &operator=(const expected_copy_assign_base &rhs) {
930  this->assign(rhs);
931  return *this;
932  }
933  expected_copy_assign_base &
934  operator=(expected_copy_assign_base &&rhs) = default;
935 };
936 
937 // This class manages conditionally having a trivial move assignment operator
938 template <class T, class E,
939  bool =
940  is_void_or<T, conjunction<std::is_trivially_destructible<T>,
941  std::is_trivially_move_constructible<T>,
942  std::is_trivially_move_assignable<T>>>::
943  value &&std::is_trivially_destructible<E>::value
944  &&std::is_trivially_move_constructible<E>::value
945  &&std::is_trivially_move_assignable<E>::value>
946 struct expected_move_assign_base : expected_copy_assign_base<T, E> {
947  using expected_copy_assign_base<T, E>::expected_copy_assign_base;
948 };
949 
950 template <class T, class E>
951 struct expected_move_assign_base<T, E, false>
952  : expected_copy_assign_base<T, E> {
953  using expected_copy_assign_base<T, E>::expected_copy_assign_base;
954 
955  expected_move_assign_base() = default;
956  expected_move_assign_base(const expected_move_assign_base &rhs) = default;
957 
958  expected_move_assign_base(expected_move_assign_base &&rhs) = default;
959 
960  expected_move_assign_base &
961  operator=(const expected_move_assign_base &rhs) = default;
962 
963  expected_move_assign_base &
964  operator=(expected_move_assign_base &&rhs) noexcept(
965  std::is_nothrow_move_constructible<T>::value
966  &&std::is_nothrow_move_assignable<T>::value) {
967  this->assign(std::move(rhs));
968  return *this;
969  }
970 };
971 
972 // expected_delete_ctor_base will conditionally delete copy and move
973 // constructors depending on whether T is copy/move constructible
974 template <class T, class E,
975  bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
976  std::is_copy_constructible<E>::value),
977  bool EnableMove = (is_move_constructible_or_void<T>::value &&
978  std::is_move_constructible<E>::value)>
979 struct expected_delete_ctor_base {
980  expected_delete_ctor_base() = default;
981  expected_delete_ctor_base(const expected_delete_ctor_base &) = default;
982  expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
983  expected_delete_ctor_base &
984  operator=(const expected_delete_ctor_base &) = default;
985  expected_delete_ctor_base &
986  operator=(expected_delete_ctor_base &&) noexcept = default;
987 };
988 
989 template <class T, class E>
990 struct expected_delete_ctor_base<T, E, true, false> {
991  expected_delete_ctor_base() = default;
992  expected_delete_ctor_base(const expected_delete_ctor_base &) = default;
993  expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
994  expected_delete_ctor_base &
995  operator=(const expected_delete_ctor_base &) = default;
996  expected_delete_ctor_base &
997  operator=(expected_delete_ctor_base &&) noexcept = default;
998 };
999 
1000 template <class T, class E>
1001 struct expected_delete_ctor_base<T, E, false, true> {
1002  expected_delete_ctor_base() = default;
1003  expected_delete_ctor_base(const expected_delete_ctor_base &) = delete;
1004  expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
1005  expected_delete_ctor_base &
1006  operator=(const expected_delete_ctor_base &) = default;
1007  expected_delete_ctor_base &
1008  operator=(expected_delete_ctor_base &&) noexcept = default;
1009 };
1010 
1011 template <class T, class E>
1012 struct expected_delete_ctor_base<T, E, false, false> {
1013  expected_delete_ctor_base() = default;
1014  expected_delete_ctor_base(const expected_delete_ctor_base &) = delete;
1015  expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
1016  expected_delete_ctor_base &
1017  operator=(const expected_delete_ctor_base &) = default;
1018  expected_delete_ctor_base &
1019  operator=(expected_delete_ctor_base &&) noexcept = default;
1020 };
1021 
1022 // expected_delete_assign_base will conditionally delete copy and move
1023 // constructors depending on whether T and E are copy/move constructible +
1024 // assignable
1025 template <class T, class E,
1026  bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1027  std::is_copy_constructible<E>::value &&
1028  is_copy_assignable_or_void<T>::value &&
1029  std::is_copy_assignable<E>::value),
1030  bool EnableMove = (is_move_constructible_or_void<T>::value &&
1031  std::is_move_constructible<E>::value &&
1032  is_move_assignable_or_void<T>::value &&
1033  std::is_move_assignable<E>::value)>
1034 struct expected_delete_assign_base {
1035  expected_delete_assign_base() = default;
1036  expected_delete_assign_base(const expected_delete_assign_base &) = default;
1037  expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1038  default;
1039  expected_delete_assign_base &
1040  operator=(const expected_delete_assign_base &) = default;
1041  expected_delete_assign_base &
1042  operator=(expected_delete_assign_base &&) noexcept = default;
1043 };
1044 
1045 template <class T, class E>
1046 struct expected_delete_assign_base<T, E, true, false> {
1047  expected_delete_assign_base() = default;
1048  expected_delete_assign_base(const expected_delete_assign_base &) = default;
1049  expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1050  default;
1051  expected_delete_assign_base &
1052  operator=(const expected_delete_assign_base &) = default;
1053  expected_delete_assign_base &
1054  operator=(expected_delete_assign_base &&) noexcept = delete;
1055 };
1056 
1057 template <class T, class E>
1058 struct expected_delete_assign_base<T, E, false, true> {
1059  expected_delete_assign_base() = default;
1060  expected_delete_assign_base(const expected_delete_assign_base &) = default;
1061  expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1062  default;
1063  expected_delete_assign_base &
1064  operator=(const expected_delete_assign_base &) = delete;
1065  expected_delete_assign_base &
1066  operator=(expected_delete_assign_base &&) noexcept = default;
1067 };
1068 
1069 template <class T, class E>
1070 struct expected_delete_assign_base<T, E, false, false> {
1071  expected_delete_assign_base() = default;
1072  expected_delete_assign_base(const expected_delete_assign_base &) = default;
1073  expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1074  default;
1075  expected_delete_assign_base &
1076  operator=(const expected_delete_assign_base &) = delete;
1077  expected_delete_assign_base &
1078  operator=(expected_delete_assign_base &&) noexcept = delete;
1079 };
1080 
1081 // This is needed to be able to construct the expected_default_ctor_base which
1082 // follows, while still conditionally deleting the default constructor.
1083 struct default_constructor_tag {
1084  explicit constexpr default_constructor_tag() = default;
1085 };
1086 
1087 // expected_default_ctor_base will ensure that expected has a deleted default
1088 // consturctor if T is not default constructible.
1089 // This specialization is for when T is default constructible
1090 template <class T, class E,
1091  bool Enable =
1092  std::is_default_constructible<T>::value || std::is_void<T>::value>
1093 struct expected_default_ctor_base {
1094  constexpr expected_default_ctor_base() noexcept = default;
1095  constexpr expected_default_ctor_base(
1096  expected_default_ctor_base const &) noexcept = default;
1097  constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
1098  default;
1099  expected_default_ctor_base &
1100  operator=(expected_default_ctor_base const &) noexcept = default;
1101  expected_default_ctor_base &
1102  operator=(expected_default_ctor_base &&) noexcept = default;
1103 
1104  constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
1105 };
1106 
1107 // This specialization is for when T is not default constructible
1108 template <class T, class E> struct expected_default_ctor_base<T, E, false> {
1109  constexpr expected_default_ctor_base() noexcept = delete;
1110  constexpr expected_default_ctor_base(
1111  expected_default_ctor_base const &) noexcept = default;
1112  constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
1113  default;
1114  expected_default_ctor_base &
1115  operator=(expected_default_ctor_base const &) noexcept = default;
1116  expected_default_ctor_base &
1117  operator=(expected_default_ctor_base &&) noexcept = default;
1118 
1119  constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
1120 };
1121 } // namespace detail
1122 
1123 template <typename E>
1124 class bad_expected_access;
1125 
1126 template <> class bad_expected_access<void> : public std::exception
1127 {
1128 public:
1129  virtual const char *what() const noexcept override {
1130  return "Bad expected access";
1131  }
1132 
1133 protected:
1134  bad_expected_access() noexcept {}
1135  bad_expected_access(const bad_expected_access&) = default;
1136  bad_expected_access(bad_expected_access&&) = default;
1137  bad_expected_access& operator=(const bad_expected_access&) = default;
1138  bad_expected_access& operator=(bad_expected_access&&) = default;
1139  ~bad_expected_access() = default;
1140 };
1141 
1142 template <class E>
1143 class bad_expected_access : public bad_expected_access<void>
1144 {
1145 public:
1146  explicit bad_expected_access(E e) : m_val(std::move(e)) {}
1147 
1148  const E &error() const & { return m_val; }
1149  E &error() & { return m_val; }
1150  const E &&error() const && { return std::move(m_val); }
1151  E &&error() && { return std::move(m_val); }
1152 
1153 private:
1154  E m_val;
1155 };
1156 
1157 template <class T, class E>
1158 class expected : private detail::expected_move_assign_base<T, E>,
1159  private detail::expected_delete_ctor_base<T, E>,
1160  private detail::expected_delete_assign_base<T, E>,
1161  private detail::expected_default_ctor_base<T, E> {
1162  static_assert(!std::is_reference<T>::value, "T must not be a reference");
1163  static_assert(!std::is_same<T, std::remove_cv<in_place_t>::type>::value,
1164  "T must not be in_place_t");
1165  static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,
1166  "T must not be unexpect_t");
1167  static_assert(
1168  !std::is_same<T, typename std::remove_cv<unexpected<E>>::type>::value,
1169  "T must not be unexpected<E>");
1170  static_assert(!std::is_reference<E>::value, "E must not be a reference");
1171 
1172  T *valptr() { return std::addressof(this->m_val); }
1173  const T *valptr() const { return std::addressof(this->m_val); }
1174  unexpected<E> *errptr() { return std::addressof(this->m_unexpect); }
1175  const unexpected<E> *errptr() const {
1176  return std::addressof(this->m_unexpect);
1177  }
1178 
1179  template <class U = T,
1180  detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1181  constexpr U &val() {
1182  return this->m_val;
1183  }
1184  constexpr unexpected<E> &err() { return this->m_unexpect; }
1185 
1186  template <class U = T,
1187  detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1188  constexpr const U &val() const {
1189  return this->m_val;
1190  }
1191  constexpr const unexpected<E> &err() const { return this->m_unexpect; }
1192 
1193  using impl_base = detail::expected_move_assign_base<T, E>;
1194  using ctor_base = detail::expected_default_ctor_base<T, E>;
1195 
1196 public:
1197  typedef T value_type;
1198  typedef E error_type;
1199  typedef unexpected<E> unexpected_type;
1200 
1201 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1202 
1203  template <class F> constexpr auto and_then(F &&f) & {
1204  return and_then_impl(*this, std::forward<F>(f));
1205  }
1206  template <class F> constexpr auto and_then(F &&f) && {
1207  return and_then_impl(std::move(*this), std::forward<F>(f));
1208  }
1209  template <class F> constexpr auto and_then(F &&f) const & {
1210  return and_then_impl(*this, std::forward<F>(f));
1211  }
1212  template <class F> constexpr auto and_then(F &&f) const && {
1213  return and_then_impl(std::move(*this), std::forward<F>(f));
1214  }
1215 
1216 #else
1217 
1218  template <class F>
1219  constexpr auto
1220  and_then(F &&f) & -> decltype(and_then_impl(std::declval<expected &>(),
1221  std::forward<F>(f))) {
1222  return and_then_impl(*this, std::forward<F>(f));
1223  }
1224  template <class F>
1225  constexpr auto
1226  and_then(F &&f) && -> decltype(and_then_impl(std::declval<expected &&>(),
1227  std::forward<F>(f))) {
1228  return and_then_impl(std::move(*this), std::forward<F>(f));
1229  }
1230  template <class F>
1231  constexpr auto and_then(F &&f) const & -> decltype(and_then_impl(
1232  std::declval<expected const &>(), std::forward<F>(f))) {
1233  return and_then_impl(*this, std::forward<F>(f));
1234  }
1235  template <class F>
1236  constexpr auto and_then(F &&f) const && -> decltype(and_then_impl(
1237  std::declval<expected const &&>(), std::forward<F>(f))) {
1238  return and_then_impl(std::move(*this), std::forward<F>(f));
1239  }
1240 
1241 #endif
1242 
1243 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1244  template <class F> constexpr auto map(F &&f) & {
1245  return expected_map_impl(*this, std::forward<F>(f));
1246  }
1247  template <class F> constexpr auto map(F &&f) && {
1248  return expected_map_impl(std::move(*this), std::forward<F>(f));
1249  }
1250  template <class F> constexpr auto map(F &&f) const & {
1251  return expected_map_impl(*this, std::forward<F>(f));
1252  }
1253  template <class F> constexpr auto map(F &&f) const && {
1254  return expected_map_impl(std::move(*this), std::forward<F>(f));
1255  }
1256 #else
1257  template <class F>
1258  constexpr decltype(expected_map_impl(
1259  std::declval<expected &>(), std::declval<F &&>()))
1260  map(F &&f) & {
1261  return expected_map_impl(*this, std::forward<F>(f));
1262  }
1263  template <class F>
1264  constexpr decltype(expected_map_impl(std::declval<expected>(),
1265  std::declval<F &&>()))
1266  map(F &&f) && {
1267  return expected_map_impl(std::move(*this), std::forward<F>(f));
1268  }
1269  template <class F>
1270  constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1271  std::declval<F &&>()))
1272  map(F &&f) const & {
1273  return expected_map_impl(*this, std::forward<F>(f));
1274  }
1275  template <class F>
1276  constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1277  std::declval<F &&>()))
1278  map(F &&f) const && {
1279  return expected_map_impl(std::move(*this), std::forward<F>(f));
1280  }
1281 #endif
1282 
1283 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1284  template <class F> constexpr auto transform(F &&f) & {
1285  return expected_map_impl(*this, std::forward<F>(f));
1286  }
1287  template <class F> constexpr auto transform(F &&f) && {
1288  return expected_map_impl(std::move(*this), std::forward<F>(f));
1289  }
1290  template <class F> constexpr auto transform(F &&f) const & {
1291  return expected_map_impl(*this, std::forward<F>(f));
1292  }
1293  template <class F> constexpr auto transform(F &&f) const && {
1294  return expected_map_impl(std::move(*this), std::forward<F>(f));
1295  }
1296 #else
1297  template <class F>
1298  constexpr decltype(expected_map_impl(
1299  std::declval<expected &>(), std::declval<F &&>()))
1300  transform(F &&f) & {
1301  return expected_map_impl(*this, std::forward<F>(f));
1302  }
1303  template <class F>
1304  constexpr decltype(expected_map_impl(std::declval<expected>(),
1305  std::declval<F &&>()))
1306  transform(F &&f) && {
1307  return expected_map_impl(std::move(*this), std::forward<F>(f));
1308  }
1309  template <class F>
1310  constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1311  std::declval<F &&>()))
1312  transform(F &&f) const & {
1313  return expected_map_impl(*this, std::forward<F>(f));
1314  }
1315  template <class F>
1316  constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1317  std::declval<F &&>()))
1318  transform(F &&f) const && {
1319  return expected_map_impl(std::move(*this), std::forward<F>(f));
1320  }
1321 #endif
1322 
1323 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1324  template <class F> constexpr auto map_error(F &&f) & {
1325  return map_error_impl(*this, std::forward<F>(f));
1326  }
1327  template <class F> constexpr auto map_error(F &&f) && {
1328  return map_error_impl(std::move(*this), std::forward<F>(f));
1329  }
1330  template <class F> constexpr auto map_error(F &&f) const & {
1331  return map_error_impl(*this, std::forward<F>(f));
1332  }
1333  template <class F> constexpr auto map_error(F &&f) const && {
1334  return map_error_impl(std::move(*this), std::forward<F>(f));
1335  }
1336 #else
1337  template <class F>
1338  constexpr decltype(map_error_impl(std::declval<expected &>(),
1339  std::declval<F &&>()))
1340  map_error(F &&f) & {
1341  return map_error_impl(*this, std::forward<F>(f));
1342  }
1343  template <class F>
1344  constexpr decltype(map_error_impl(std::declval<expected &&>(),
1345  std::declval<F &&>()))
1346  map_error(F &&f) && {
1347  return map_error_impl(std::move(*this), std::forward<F>(f));
1348  }
1349  template <class F>
1350  constexpr decltype(map_error_impl(std::declval<const expected &>(),
1351  std::declval<F &&>()))
1352  map_error(F &&f) const & {
1353  return map_error_impl(*this, std::forward<F>(f));
1354  }
1355  template <class F>
1356  constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1357  std::declval<F &&>()))
1358  map_error(F &&f) const && {
1359  return map_error_impl(std::move(*this), std::forward<F>(f));
1360  }
1361 #endif
1362 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1363  template <class F> constexpr auto transform_error(F &&f) & {
1364  return map_error_impl(*this, std::forward<F>(f));
1365  }
1366  template <class F> constexpr auto transform_error(F &&f) && {
1367  return map_error_impl(std::move(*this), std::forward<F>(f));
1368  }
1369  template <class F> constexpr auto transform_error(F &&f) const & {
1370  return map_error_impl(*this, std::forward<F>(f));
1371  }
1372  template <class F> constexpr auto transform_error(F &&f) const && {
1373  return map_error_impl(std::move(*this), std::forward<F>(f));
1374  }
1375 #else
1376  template <class F>
1377  constexpr decltype(map_error_impl(std::declval<expected &>(),
1378  std::declval<F &&>()))
1379  transform_error(F &&f) & {
1380  return map_error_impl(*this, std::forward<F>(f));
1381  }
1382  template <class F>
1383  constexpr decltype(map_error_impl(std::declval<expected &&>(),
1384  std::declval<F &&>()))
1385  transform_error(F &&f) && {
1386  return map_error_impl(std::move(*this), std::forward<F>(f));
1387  }
1388  template <class F>
1389  constexpr decltype(map_error_impl(std::declval<const expected &>(),
1390  std::declval<F &&>()))
1391  transform_error(F &&f) const & {
1392  return map_error_impl(*this, std::forward<F>(f));
1393  }
1394  template <class F>
1395  constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1396  std::declval<F &&>()))
1397  transform_error(F &&f) const && {
1398  return map_error_impl(std::move(*this), std::forward<F>(f));
1399  }
1400 #endif
1401  template <class F> expected constexpr or_else(F &&f) & {
1402  return or_else_impl(*this, std::forward<F>(f));
1403  }
1404 
1405  template <class F> expected constexpr or_else(F &&f) && {
1406  return or_else_impl(std::move(*this), std::forward<F>(f));
1407  }
1408 
1409  template <class F> expected constexpr or_else(F &&f) const & {
1410  return or_else_impl(*this, std::forward<F>(f));
1411  }
1412 
1413  template <class F> expected constexpr or_else(F &&f) const && {
1414  return or_else_impl(std::move(*this), std::forward<F>(f));
1415  }
1416 
1417  constexpr expected() = default;
1418  constexpr expected(const expected &rhs) = default;
1419  constexpr expected(expected &&rhs) = default;
1420  expected &operator=(const expected &rhs) = default;
1421  expected &operator=(expected &&rhs) = default;
1422 
1423  template <class... Args,
1424  detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
1425  nullptr>
1426  constexpr expected(in_place_t, Args &&...args)
1427  : impl_base(in_place, std::forward<Args>(args)...),
1428  ctor_base(detail::default_constructor_tag{}) {}
1429 
1430  template <class U, class... Args,
1431  detail::enable_if_t<std::is_constructible<
1432  T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1433  constexpr expected(in_place_t, std::initializer_list<U> il, Args &&...args)
1434  : impl_base(in_place, il, std::forward<Args>(args)...),
1435  ctor_base(detail::default_constructor_tag{}) {}
1436 
1437  template <class G = E,
1438  detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
1439  nullptr,
1440  detail::enable_if_t<!std::is_convertible<const G &, E>::value> * =
1441  nullptr>
1442  explicit constexpr expected(const unexpected<G> &e)
1443  : impl_base(unexpect, e.value()),
1444  ctor_base(detail::default_constructor_tag{}) {}
1445 
1446  template <
1447  class G = E,
1448  detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
1449  nullptr,
1450  detail::enable_if_t<std::is_convertible<const G &, E>::value> * = nullptr>
1451  constexpr expected(unexpected<G> const &e)
1452  : impl_base(unexpect, e.value()),
1453  ctor_base(detail::default_constructor_tag{}) {}
1454 
1455  template <
1456  class G = E,
1457  detail::enable_if_t<std::is_constructible<E, G &&>::value> * = nullptr,
1458  detail::enable_if_t<!std::is_convertible<G &&, E>::value> * = nullptr>
1459  explicit constexpr expected(unexpected<G> &&e) noexcept(
1460  std::is_nothrow_constructible<E, G &&>::value)
1461  : impl_base(unexpect, std::move(e.value())),
1462  ctor_base(detail::default_constructor_tag{}) {}
1463 
1464  template <
1465  class G = E,
1466  detail::enable_if_t<std::is_constructible<E, G &&>::value> * = nullptr,
1467  detail::enable_if_t<std::is_convertible<G &&, E>::value> * = nullptr>
1468  constexpr expected(unexpected<G> &&e) noexcept(
1469  std::is_nothrow_constructible<E, G &&>::value)
1470  : impl_base(unexpect, std::move(e.value())),
1471  ctor_base(detail::default_constructor_tag{}) {}
1472 
1473  template <class... Args,
1474  detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
1475  nullptr>
1476  constexpr explicit expected(unexpect_t, Args &&...args)
1477  : impl_base(unexpect, std::forward<Args>(args)...),
1478  ctor_base(detail::default_constructor_tag{}) {}
1479 
1480  template <class U, class... Args,
1481  detail::enable_if_t<std::is_constructible<
1482  E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1483  constexpr explicit expected(unexpect_t, std::initializer_list<U> il,
1484  Args &&...args)
1485  : impl_base(unexpect, il, std::forward<Args>(args)...),
1486  ctor_base(detail::default_constructor_tag{}) {}
1487 
1488  template <class U, class G,
1489  detail::enable_if_t<!(std::is_convertible<U const &, T>::value &&
1490  std::is_convertible<G const &, E>::value)> * =
1491  nullptr,
1492  detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1493  * = nullptr>
1494  explicit constexpr expected(const expected<U, G> &rhs)
1495  : ctor_base(detail::default_constructor_tag{}) {
1496  if (rhs.has_value()) {
1497  this->construct(*rhs);
1498  } else {
1499  this->construct_error(rhs.error());
1500  }
1501  }
1502 
1503  template <class U, class G,
1504  detail::enable_if_t<(std::is_convertible<U const &, T>::value &&
1505  std::is_convertible<G const &, E>::value)> * =
1506  nullptr,
1507  detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1508  * = nullptr>
1509  constexpr expected(const expected<U, G> &rhs)
1510  : ctor_base(detail::default_constructor_tag{}) {
1511  if (rhs.has_value()) {
1512  this->construct(*rhs);
1513  } else {
1514  this->construct_error(rhs.error());
1515  }
1516  }
1517 
1518  template <
1519  class U, class G,
1520  detail::enable_if_t<!(std::is_convertible<U &&, T>::value &&
1521  std::is_convertible<G &&, E>::value)> * = nullptr,
1522  detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * = nullptr>
1523  explicit constexpr expected(expected<U, G> &&rhs)
1524  : ctor_base(detail::default_constructor_tag{}) {
1525  if (rhs.has_value()) {
1526  this->construct(std::move(*rhs));
1527  } else {
1528  this->construct_error(std::move(rhs.error()));
1529  }
1530  }
1531 
1532  template <
1533  class U, class G,
1534  detail::enable_if_t<(std::is_convertible<U &&, T>::value &&
1535  std::is_convertible<G &&, E>::value)> * = nullptr,
1536  detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * = nullptr>
1537  constexpr expected(expected<U, G> &&rhs)
1538  : ctor_base(detail::default_constructor_tag{}) {
1539  if (rhs.has_value()) {
1540  this->construct(std::move(*rhs));
1541  } else {
1542  this->construct_error(std::move(rhs.error()));
1543  }
1544  }
1545 
1546  template <
1547  class U = T,
1548  detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,
1549  detail::expected_enable_forward_value<T, E, U> * = nullptr>
1550  explicit constexpr expected(U &&v)
1551  : expected(in_place, std::forward<U>(v)) {}
1552 
1553  template <
1554  class U = T,
1555  detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,
1556  detail::expected_enable_forward_value<T, E, U> * = nullptr>
1557  constexpr expected(U &&v)
1558  : expected(in_place, std::forward<U>(v)) {}
1559 
1560  template <
1561  class U = T, class G = T,
1562  detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
1563  nullptr,
1564  detail::enable_if_t<!std::is_void<G>::value> * = nullptr,
1565  detail::enable_if_t<
1566  (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1567  !detail::conjunction<std::is_scalar<T>,
1568  std::is_same<T, detail::decay_t<U>>>::value &&
1569  std::is_constructible<T, U>::value &&
1570  std::is_assignable<G &, U>::value &&
1571  std::is_nothrow_move_constructible<E>::value)> * = nullptr>
1572  expected &operator=(U &&v) {
1573  if (has_value()) {
1574  val() = std::forward<U>(v);
1575  } else {
1576  err().~unexpected<E>();
1577  ::new (valptr()) T(std::forward<U>(v));
1578  this->m_has_val = true;
1579  }
1580 
1581  return *this;
1582  }
1583 
1584  template <
1585  class U = T, class G = T,
1586  detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =
1587  nullptr,
1588  detail::enable_if_t<!std::is_void<U>::value> * = nullptr,
1589  detail::enable_if_t<
1590  (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1591  !detail::conjunction<std::is_scalar<T>,
1592  std::is_same<T, detail::decay_t<U>>>::value &&
1593  std::is_constructible<T, U>::value &&
1594  std::is_assignable<G &, U>::value &&
1595  std::is_nothrow_move_constructible<E>::value)> * = nullptr>
1596  expected &operator=(U &&v) {
1597  if (has_value()) {
1598  val() = std::forward<U>(v);
1599  } else {
1600  auto tmp = std::move(err());
1601  err().~unexpected<E>();
1602 
1603 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1604  try {
1605  ::new (valptr()) T(std::forward<U>(v));
1606  this->m_has_val = true;
1607  } catch (...) {
1608  err() = std::move(tmp);
1609  throw;
1610  }
1611 #else
1612  ::new (valptr()) T(std::forward<U>(v));
1613  this->m_has_val = true;
1614 #endif
1615  }
1616 
1617  return *this;
1618  }
1619 
1620  template <class G = E,
1621  detail::enable_if_t<std::is_nothrow_copy_constructible<G>::value &&
1622  std::is_assignable<G &, G>::value> * = nullptr>
1623  expected &operator=(const unexpected<G> &rhs) {
1624  if (!has_value()) {
1625  err() = rhs;
1626  } else {
1627  this->destroy_val();
1628  ::new (errptr()) unexpected<E>(rhs);
1629  this->m_has_val = false;
1630  }
1631 
1632  return *this;
1633  }
1634 
1635  template <class G = E,
1636  detail::enable_if_t<std::is_nothrow_move_constructible<G>::value &&
1637  std::is_move_assignable<G>::value> * = nullptr>
1638  expected &operator=(unexpected<G> &&rhs) noexcept {
1639  if (!has_value()) {
1640  err() = std::move(rhs);
1641  } else {
1642  this->destroy_val();
1643  ::new (errptr()) unexpected<E>(std::move(rhs));
1644  this->m_has_val = false;
1645  }
1646 
1647  return *this;
1648  }
1649 
1650  template <class... Args, detail::enable_if_t<std::is_nothrow_constructible<
1651  T, Args &&...>::value> * = nullptr>
1652  void emplace(Args &&...args) {
1653  if (has_value()) {
1654  val().~T();
1655  } else {
1656  err().~unexpected<E>();
1657  this->m_has_val = true;
1658  }
1659  ::new (valptr()) T(std::forward<Args>(args)...);
1660  }
1661 
1662  template <class... Args, detail::enable_if_t<!std::is_nothrow_constructible<
1663  T, Args &&...>::value> * = nullptr>
1664  void emplace(Args &&...args) {
1665  if (has_value()) {
1666  val().~T();
1667  ::new (valptr()) T(std::forward<Args>(args)...);
1668  } else {
1669  auto tmp = std::move(err());
1670  err().~unexpected<E>();
1671 
1672 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1673  try {
1674  ::new (valptr()) T(std::forward<Args>(args)...);
1675  this->m_has_val = true;
1676  } catch (...) {
1677  err() = std::move(tmp);
1678  throw;
1679  }
1680 #else
1681  ::new (valptr()) T(std::forward<Args>(args)...);
1682  this->m_has_val = true;
1683 #endif
1684  }
1685  }
1686 
1687  template <class U, class... Args,
1688  detail::enable_if_t<std::is_nothrow_constructible<
1689  T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1690  void emplace(std::initializer_list<U> il, Args &&...args) {
1691  if (has_value()) {
1692  T t(il, std::forward<Args>(args)...);
1693  val() = std::move(t);
1694  } else {
1695  err().~unexpected<E>();
1696  ::new (valptr()) T(il, std::forward<Args>(args)...);
1697  this->m_has_val = true;
1698  }
1699  }
1700 
1701  template <class U, class... Args,
1702  detail::enable_if_t<!std::is_nothrow_constructible<
1703  T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1704  void emplace(std::initializer_list<U> il, Args &&...args) {
1705  if (has_value()) {
1706  T t(il, std::forward<Args>(args)...);
1707  val() = std::move(t);
1708  } else {
1709  auto tmp = std::move(err());
1710  err().~unexpected<E>();
1711 
1712 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1713  try {
1714  ::new (valptr()) T(il, std::forward<Args>(args)...);
1715  this->m_has_val = true;
1716  } catch (...) {
1717  err() = std::move(tmp);
1718  throw;
1719  }
1720 #else
1721  ::new (valptr()) T(il, std::forward<Args>(args)...);
1722  this->m_has_val = true;
1723 #endif
1724  }
1725  }
1726 
1727 private:
1728  using t_is_void = std::true_type;
1729  using t_is_not_void = std::false_type;
1730  using t_is_nothrow_move_constructible = std::true_type;
1731  using move_constructing_t_can_throw = std::false_type;
1732  using e_is_nothrow_move_constructible = std::true_type;
1733  using move_constructing_e_can_throw = std::false_type;
1734 
1735  void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept {
1736  // swapping void is a no-op
1737  }
1738 
1739  void swap_where_both_have_value(expected &rhs, t_is_not_void) {
1740  using std::swap;
1741  swap(val(), rhs.val());
1742  }
1743 
1744  void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept(
1745  std::is_nothrow_move_constructible<E>::value) {
1746  ::new (errptr()) unexpected_type(std::move(rhs.err()));
1747  rhs.err().~unexpected_type();
1748  std::swap(this->m_has_val, rhs.m_has_val);
1749  }
1750 
1751  void swap_where_only_one_has_value(expected &rhs, t_is_not_void) {
1752  swap_where_only_one_has_value_and_t_is_not_void(
1753  rhs, typename std::is_nothrow_move_constructible<T>::type{},
1754  typename std::is_nothrow_move_constructible<E>::type{});
1755  }
1756 
1757  void swap_where_only_one_has_value_and_t_is_not_void(
1758  expected &rhs, t_is_nothrow_move_constructible,
1759  e_is_nothrow_move_constructible) noexcept {
1760  auto temp = std::move(val());
1761  val().~T();
1762  ::new (errptr()) unexpected_type(std::move(rhs.err()));
1763  rhs.err().~unexpected_type();
1764  ::new (rhs.valptr()) T(std::move(temp));
1765  std::swap(this->m_has_val, rhs.m_has_val);
1766  }
1767 
1768  void swap_where_only_one_has_value_and_t_is_not_void(
1769  expected &rhs, t_is_nothrow_move_constructible,
1770  move_constructing_e_can_throw) {
1771  auto temp = std::move(val());
1772  val().~T();
1773 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1774  try {
1775  ::new (errptr()) unexpected_type(std::move(rhs.err()));
1776  rhs.err().~unexpected_type();
1777  ::new (rhs.valptr()) T(std::move(temp));
1778  std::swap(this->m_has_val, rhs.m_has_val);
1779  } catch (...) {
1780  val() = std::move(temp);
1781  throw;
1782  }
1783 #else
1784  ::new (errptr()) unexpected_type(std::move(rhs.err()));
1785  rhs.err().~unexpected_type();
1786  ::new (rhs.valptr()) T(std::move(temp));
1787  std::swap(this->m_has_val, rhs.m_has_val);
1788 #endif
1789  }
1790 
1791  void swap_where_only_one_has_value_and_t_is_not_void(
1792  expected &rhs, move_constructing_t_can_throw,
1793  e_is_nothrow_move_constructible) {
1794  auto temp = std::move(rhs.err());
1795  rhs.err().~unexpected_type();
1796 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1797  try {
1798  ::new (rhs.valptr()) T(std::move(val()));
1799  val().~T();
1800  ::new (errptr()) unexpected_type(std::move(temp));
1801  std::swap(this->m_has_val, rhs.m_has_val);
1802  } catch (...) {
1803  rhs.err() = std::move(temp);
1804  throw;
1805  }
1806 #else
1807  ::new (rhs.valptr()) T(std::move(val()));
1808  val().~T();
1809  ::new (errptr()) unexpected_type(std::move(temp));
1810  std::swap(this->m_has_val, rhs.m_has_val);
1811 #endif
1812  }
1813 
1814 public:
1815  template <class OT = T, class OE = E>
1816  detail::enable_if_t<detail::is_swappable<OT>::value &&
1817  detail::is_swappable<OE>::value &&
1818  (std::is_nothrow_move_constructible<OT>::value ||
1819  std::is_nothrow_move_constructible<OE>::value)>
1820  swap(expected &rhs) noexcept(
1821  std::is_nothrow_move_constructible<T>::value
1822  &&detail::is_nothrow_swappable<T>::value
1823  &&std::is_nothrow_move_constructible<E>::value
1824  &&detail::is_nothrow_swappable<E>::value) {
1825  if (has_value() && rhs.has_value()) {
1826  swap_where_both_have_value(rhs, typename std::is_void<T>::type{});
1827  } else if (!has_value() && rhs.has_value()) {
1828  rhs.swap(*this);
1829  } else if (has_value()) {
1830  swap_where_only_one_has_value(rhs, typename std::is_void<T>::type{});
1831  } else {
1832  using std::swap;
1833  swap(err(), rhs.err());
1834  }
1835  }
1836 
1837  constexpr const T *operator->() const {
1838  assert(has_value());
1839  return valptr();
1840  }
1841  constexpr T *operator->() {
1842  assert(has_value());
1843  return valptr();
1844  }
1845 
1846  template <class U = T,
1847  detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1848  constexpr const U &operator*() const & {
1849  assert(has_value());
1850  return val();
1851  }
1852  template <class U = T,
1853  detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1854  constexpr U &operator*() & {
1855  assert(has_value());
1856  return val();
1857  }
1858  template <class U = T,
1859  detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1860  constexpr const U &&operator*() const && {
1861  assert(has_value());
1862  return std::move(val());
1863  }
1864  template <class U = T,
1865  detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1866  constexpr U &&operator*() && {
1867  assert(has_value());
1868  return std::move(val());
1869  }
1870 
1871  constexpr bool has_value() const noexcept { return this->m_has_val; }
1872  constexpr explicit operator bool() const noexcept { return this->m_has_val; }
1873 
1874  template <class U = T,
1875  detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1876  constexpr const U &value() const & {
1877  if (!has_value())
1878  detail::throw_exception(bad_expected_access<E>(err().value()));
1879  return val();
1880  }
1881  template <class U = T,
1882  detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1883  constexpr U &value() & {
1884  if (!has_value())
1885  detail::throw_exception(bad_expected_access<E>(err().value()));
1886  return val();
1887  }
1888  template <class U = T,
1889  detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1890  constexpr const U &&value() const && {
1891  if (!has_value())
1892  detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));
1893  return std::move(val());
1894  }
1895  template <class U = T,
1896  detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1897  constexpr U &&value() && {
1898  if (!has_value())
1899  detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));
1900  return std::move(val());
1901  }
1902 
1903  constexpr const E &error() const & {
1904  assert(!has_value());
1905  return err().value();
1906  }
1907  constexpr E &error() & {
1908  assert(!has_value());
1909  return err().value();
1910  }
1911  constexpr const E &&error() const && {
1912  assert(!has_value());
1913  return std::move(err().value());
1914  }
1915  constexpr E &&error() && {
1916  assert(!has_value());
1917  return std::move(err().value());
1918  }
1919 
1920  template <class U> constexpr T value_or(U &&v) const & {
1921  static_assert(std::is_copy_constructible<T>::value &&
1922  std::is_convertible<U &&, T>::value,
1923  "T must be copy-constructible and convertible to from U&&");
1924  return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
1925  }
1926  template <class U> constexpr T value_or(U &&v) && {
1927  static_assert(std::is_move_constructible<T>::value &&
1928  std::is_convertible<U &&, T>::value,
1929  "T must be move-constructible and convertible to from U&&");
1930  return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));
1931  }
1932 };
1933 
1934 namespace detail {
1935 template <class Exp> using exp_t = typename detail::decay_t<Exp>::value_type;
1936 template <class Exp> using err_t = typename detail::decay_t<Exp>::error_type;
1937 template <class Exp, class Ret> using ret_t = expected<Ret, err_t<Exp>>;
1938 
1939 template <class Exp, class F,
1940  detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
1941  class Ret = decltype(invoke(std::declval<F>(),
1942  *std::declval<Exp>()))>
1943 constexpr auto and_then_impl(Exp &&exp, F &&f) {
1944  static_assert(detail::is_expected<Ret>::value, "F must return an expected");
1945 
1946  return exp.has_value()
1947  ? invoke(std::forward<F>(f), *std::forward<Exp>(exp))
1948  : Ret(unexpect, std::forward<Exp>(exp).error());
1949 }
1950 
1951 template <class Exp, class F,
1952  detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
1953  class Ret = decltype(invoke(std::declval<F>()))>
1954 constexpr auto and_then_impl(Exp &&exp, F &&f) {
1955  static_assert(detail::is_expected<Ret>::value, "F must return an expected");
1956 
1957  return exp.has_value() ? invoke(std::forward<F>(f))
1958  : Ret(unexpect, std::forward<Exp>(exp).error());
1959 }
1960 
1961 template <class Exp, class F,
1962  detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
1963  class Ret = decltype(invoke(std::declval<F>(),
1964  *std::declval<Exp>())),
1965  detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
1966 constexpr auto expected_map_impl(Exp &&exp, F &&f) {
1967  using result = ret_t<Exp, detail::decay_t<Ret>>;
1968  return exp.has_value() ? result(invoke(std::forward<F>(f),
1969  *std::forward<Exp>(exp)))
1970  : result(unexpect, std::forward<Exp>(exp).error());
1971 }
1972 
1973 template <class Exp, class F,
1974  detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
1975  class Ret = decltype(invoke(std::declval<F>(),
1976  *std::declval<Exp>())),
1977  detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
1978 auto expected_map_impl(Exp &&exp, F &&f) {
1979  using result = expected<void, err_t<Exp>>;
1980  if (exp.has_value()) {
1981  invoke(std::forward<F>(f), *std::forward<Exp>(exp));
1982  return result();
1983  }
1984 
1985  return result(unexpect, std::forward<Exp>(exp).error());
1986 }
1987 
1988 template <class Exp, class F,
1989  detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
1990  class Ret = decltype(invoke(std::declval<F>())),
1991  detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
1992 constexpr auto expected_map_impl(Exp &&exp, F &&f) {
1993  using result = ret_t<Exp, detail::decay_t<Ret>>;
1994  return exp.has_value() ? result(invoke(std::forward<F>(f)))
1995  : result(unexpect, std::forward<Exp>(exp).error());
1996 }
1997 
1998 template <class Exp, class F,
1999  detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2000  class Ret = decltype(invoke(std::declval<F>())),
2001  detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2002 auto expected_map_impl(Exp &&exp, F &&f) {
2003  using result = expected<void, err_t<Exp>>;
2004  if (exp.has_value()) {
2005  invoke(std::forward<F>(f));
2006  return result();
2007  }
2008 
2009  return result(unexpect, std::forward<Exp>(exp).error());
2010 }
2011 
2012 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
2013 template <class Exp, class F,
2014  detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2015  class Ret = decltype(invoke(std::declval<F>(),
2016  std::declval<Exp>().error())),
2017  detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2018 constexpr auto map_error_impl(Exp &&exp, F &&f) {
2019  using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2020  return exp.has_value()
2021  ? result(*std::forward<Exp>(exp))
2022  : result(unexpect, invoke(std::forward<F>(f),
2023  std::forward<Exp>(exp).error()));
2024 }
2025 template <class Exp, class F,
2026  detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2027  class Ret = decltype(invoke(std::declval<F>(),
2028  std::declval<Exp>().error())),
2029  detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2030 auto map_error_impl(Exp &&exp, F &&f) {
2031  using result = expected<exp_t<Exp>, monostate>;
2032  if (exp.has_value()) {
2033  return result(*std::forward<Exp>(exp));
2034  }
2035 
2036  invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2037  return result(unexpect, monostate{});
2038 }
2039 template <class Exp, class F,
2040  detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2041  class Ret = decltype(invoke(std::declval<F>(),
2042  std::declval<Exp>().error())),
2043  detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2044 constexpr auto map_error_impl(Exp &&exp, F &&f) {
2045  using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2046  return exp.has_value()
2047  ? result()
2048  : result(unexpect, invoke(std::forward<F>(f),
2049  std::forward<Exp>(exp).error()));
2050 }
2051 template <class Exp, class F,
2052  detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2053  class Ret = decltype(invoke(std::declval<F>(),
2054  std::declval<Exp>().error())),
2055  detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2056 auto map_error_impl(Exp &&exp, F &&f) {
2057  using result = expected<exp_t<Exp>, monostate>;
2058  if (exp.has_value()) {
2059  return result();
2060  }
2061 
2062  invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2063  return result(unexpect, monostate{});
2064 }
2065 #else
2066 template <class Exp, class F,
2067  detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2068  class Ret = decltype(invoke(std::declval<F>(),
2069  std::declval<Exp>().error())),
2070  detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2071 constexpr auto map_error_impl(Exp &&exp, F &&f)
2072  -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
2073  using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2074 
2075  return exp.has_value()
2076  ? result(*std::forward<Exp>(exp))
2077  : result(unexpect, invoke(std::forward<F>(f),
2078  std::forward<Exp>(exp).error()));
2079 }
2080 
2081 template <class Exp, class F,
2082  detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2083  class Ret = decltype(invoke(std::declval<F>(),
2084  std::declval<Exp>().error())),
2085  detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2086 auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2087  using result = expected<exp_t<Exp>, monostate>;
2088  if (exp.has_value()) {
2089  return result(*std::forward<Exp>(exp));
2090  }
2091 
2092  invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2093  return result(unexpect, monostate{});
2094 }
2095 
2096 template <class Exp, class F,
2097  detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2098  class Ret = decltype(invoke(std::declval<F>(),
2099  std::declval<Exp>().error())),
2100  detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2101 constexpr auto map_error_impl(Exp &&exp, F &&f)
2102  -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
2103  using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2104 
2105  return exp.has_value()
2106  ? result()
2107  : result(unexpect, invoke(std::forward<F>(f), std::forward<Exp>(exp).error()));
2108 }
2109 
2110 template <class Exp, class F,
2111  detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2112  class Ret = decltype(invoke(std::declval<F>(),
2113  std::declval<Exp>().error())),
2114  detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2115 auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2116  using result = expected<exp_t<Exp>, monostate>;
2117  if (exp.has_value()) {
2118  return result();
2119  }
2120 
2121  invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2122  return result(unexpect, monostate{});
2123 }
2124 #endif
2125 
2126 template <class Exp, class F,
2127  class Ret = decltype(invoke(std::declval<F>(),
2128  std::declval<Exp>().error())),
2129  detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2130 constexpr auto or_else_impl(Exp &&exp, F &&f) {
2131  static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2132  return exp.has_value() ? std::forward<Exp>(exp)
2133  : invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2134 }
2135 
2136 template <class Exp, class F,
2137  class Ret = decltype(invoke(std::declval<F>(),
2138  std::declval<Exp>().error())),
2139  detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2140 detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
2141  return exp.has_value() ? std::forward<Exp>(exp)
2142  : (invoke(std::forward<F>(f), std::forward<Exp>(exp).error()),
2143  std::forward<Exp>(exp));
2144 }
2145 
2146 } // namespace detail
2147 
2148 template <class T, class E, class U, class F>
2149 constexpr bool operator==(const expected<T, E> &lhs,
2150  const expected<U, F> &rhs) {
2151  return (lhs.has_value() != rhs.has_value())
2152  ? false
2153  : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
2154 }
2155 template <class T, class E, class U, class F>
2156 constexpr bool operator!=(const expected<T, E> &lhs,
2157  const expected<U, F> &rhs) {
2158  return (lhs.has_value() != rhs.has_value())
2159  ? true
2160  : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);
2161 }
2162 template <class E, class F>
2163 constexpr bool operator==(const expected<void, E> &lhs,
2164  const expected<void, F> &rhs) {
2165  return (lhs.has_value() != rhs.has_value())
2166  ? false
2167  : (!lhs.has_value() ? lhs.error() == rhs.error() : true);
2168 }
2169 template <class E, class F>
2170 constexpr bool operator!=(const expected<void, E> &lhs,
2171  const expected<void, F> &rhs) {
2172  return (lhs.has_value() != rhs.has_value())
2173  ? true
2174  : (!lhs.has_value() ? lhs.error() == rhs.error() : false);
2175 }
2176 
2177 template <class T, class E, class U>
2178 constexpr bool operator==(const expected<T, E> &x, const U &v) {
2179  return x.has_value() ? *x == v : false;
2180 }
2181 template <class T, class E, class U>
2182 constexpr bool operator==(const U &v, const expected<T, E> &x) {
2183  return x.has_value() ? *x == v : false;
2184 }
2185 template <class T, class E, class U>
2186 constexpr bool operator!=(const expected<T, E> &x, const U &v) {
2187  return x.has_value() ? *x != v : true;
2188 }
2189 template <class T, class E, class U>
2190 constexpr bool operator!=(const U &v, const expected<T, E> &x) {
2191  return x.has_value() ? *x != v : true;
2192 }
2193 
2194 template <class T, class E>
2195 constexpr bool operator==(const expected<T, E> &x, const unexpected<E> &e) {
2196  return x.has_value() ? false : x.error() == e.value();
2197 }
2198 template <class T, class E>
2199 constexpr bool operator==(const unexpected<E> &e, const expected<T, E> &x) {
2200  return x.has_value() ? false : x.error() == e.value();
2201 }
2202 template <class T, class E>
2203 constexpr bool operator!=(const expected<T, E> &x, const unexpected<E> &e) {
2204  return x.has_value() ? true : x.error() != e.value();
2205 }
2206 template <class T, class E>
2207 constexpr bool operator!=(const unexpected<E> &e, const expected<T, E> &x) {
2208  return x.has_value() ? true : x.error() != e.value();
2209 }
2210 
2211 template <class T, class E,
2212  detail::enable_if_t<(std::is_void<T>::value ||
2213  std::is_move_constructible<T>::value) &&
2214  detail::is_swappable<T>::value &&
2215  std::is_move_constructible<E>::value &&
2216  detail::is_swappable<E>::value> * = nullptr>
2217 void swap(expected<T, E> &lhs,
2218  expected<T, E> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
2219  lhs.swap(rhs);
2220 }
2221 
2223 
2225 
2226 } // namespace gul14
2227 
2228 #endif
The exception thrown by gul14::expected if value() is called, but no value is present.
Definition: expected.h:55
An expected<T, E> is an object that normally contains an "expected" object of type T,...
Definition: expected.h:93
Class template for constructing the unexpected value of an expected object.
Definition: expected.h:101
void swap(SmallVector< ElementT, in_capacity > &a, SmallVector< ElementT, in_capacity > &b)
Exchange the contents of one SmallVector with those of another one.
Definition: SmallVector.h:1656
constexpr auto get(span< E, S > s) -> decltype(s[N])
Return a reference to the Nth element of a given span.
Definition: span.h:544
constexpr auto invoke(F &&f, Args &&... args) noexcept(noexcept(detail_invoke::invoke(std::forward< F >(f), std::forward< Args >(args)...))) -> decltype(detail_invoke::invoke(std::forward< F >(f), std::forward< Args >(args)...))
Invoke a callable object f with the given arguments.
Definition: traits.h:201
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
Some metaprogramming traits for the General Utility Library.
Declaration of the in_place_t family of types and constants and of the monostate type.