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