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