19#ifndef M5_UTILITY_STL_EXPECTED_HPP
20#define M5_UTILITY_STL_EXPECTED_HPP
22#define TL_EXPECTED_VERSION_MAJOR 1
23#define TL_EXPECTED_VERSION_MINOR 1
24#define TL_EXPECTED_VERSION_PATCH 0
31#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
32#define TL_EXPECTED_EXCEPTIONS_ENABLED
35#if (defined(_MSC_VER) && _MSC_VER == 1900)
36#define TL_EXPECTED_MSVC2015
37#define TL_EXPECTED_MSVC2015_CONSTEXPR
39#define TL_EXPECTED_MSVC2015_CONSTEXPR constexpr
42#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
43#define TL_EXPECTED_GCC49
46#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__))
47#define TL_EXPECTED_GCC54
50#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__))
51#define TL_EXPECTED_GCC55
54#if !defined(TL_ASSERT)
59#if (__cplusplus > 201103L) && !defined(TL_EXPECTED_GCC49) && !defined(ESP8266)
61#define TL_ASSERT(x) assert(x)
67#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
70#define TL_EXPECTED_NO_CONSTRR
72#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor<T>
73#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>
76#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>
80#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
81#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
82#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
87struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T> {};
89template <
class T,
class A>
90struct is_trivially_copy_constructible<std::vector<T, A>> : std::false_type {};
97#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) stl::detail::is_trivially_copy_constructible<T>
98#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>
99#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>
101#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible<T>
102#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>
103#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>
106#if __cplusplus > 201103L
107#define TL_EXPECTED_CXX14
110#ifdef TL_EXPECTED_GCC49
111#define TL_EXPECTED_GCC49_CONSTEXPR
113#define TL_EXPECTED_GCC49_CONSTEXPR constexpr
116#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || defined(TL_EXPECTED_GCC49))
117#define TL_EXPECTED_11_CONSTEXPR
119#define TL_EXPECTED_11_CONSTEXPR constexpr
124template <
class T,
class E>
127#ifndef TL_MONOSTATE_INPLACE_MUTEX
128#define TL_MONOSTATE_INPLACE_MUTEX
132 explicit in_place_t() =
default;
134static constexpr in_place_t in_place{};
140 static_assert(!std::is_same<E, void>::value,
"E must not be void");
143 constexpr explicit unexpected(
const E &e) : m_val(e)
147 constexpr explicit unexpected(E &&e) : m_val(std::move(e))
151 template <
class... Args,
typename std::enable_if<std::is_constructible<E, Args &&...>::value>::type * =
nullptr>
152 constexpr explicit unexpected(Args &&...args) : m_val(std::forward<Args>(args)...)
155 template <
class U,
class... Args,
156 typename std::enable_if<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value>::type * =
158 constexpr explicit unexpected(std::initializer_list<U> l, Args &&...args) : m_val(l, std::forward<Args>(args)...)
162 constexpr const E &value()
const &
166 TL_EXPECTED_11_CONSTEXPR E &value() &
170 TL_EXPECTED_11_CONSTEXPR E &&value() &&
172 return std::move(m_val);
174 constexpr const E &&value()
const &&
176 return std::move(m_val);
183#ifdef __cpp_deduction_guides
191 return lhs.value() == rhs.value();
194constexpr bool operator!=(
const unexpected<E> &lhs,
const unexpected<E> &rhs)
196 return lhs.value() != rhs.value();
199constexpr bool operator<(
const unexpected<E> &lhs,
const unexpected<E> &rhs)
201 return lhs.value() < rhs.value();
204constexpr bool operator<=(
const unexpected<E> &lhs,
const unexpected<E> &rhs)
206 return lhs.value() <= rhs.value();
209constexpr bool operator>(
const unexpected<E> &lhs,
const unexpected<E> &rhs)
211 return lhs.value() > rhs.value();
214constexpr bool operator>=(
const unexpected<E> &lhs,
const unexpected<E> &rhs)
216 return lhs.value() >= rhs.value();
220unexpected<typename std::decay<E>::type> make_unexpected(E &&e)
222 return unexpected<typename std::decay<E>::type>(std::forward<E>(e));
232[[noreturn]] TL_EXPECTED_11_CONSTEXPR
void throw_exception(E &&e)
234#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
235 throw std::forward<E>(e);
241 __builtin_unreachable();
246#ifndef TL_TRAITS_MUTEX
247#define TL_TRAITS_MUTEX
250using remove_const_t =
typename std::remove_const<T>::type;
252using remove_reference_t =
typename std::remove_reference<T>::type;
254using decay_t =
typename std::decay<T>::type;
255template <
bool E,
class T =
void>
256using enable_if_t =
typename std::enable_if<E, T>::type;
257template <
bool B,
class T,
class F>
258using conditional_t =
typename std::conditional<B, T, F>::type;
262struct conjunction : std::true_type {};
264struct conjunction<B> : B {};
265template <
class B,
class... Bs>
266struct conjunction<B, Bs...> : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
268#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
269#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
275#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
277struct is_pointer_to_non_const_member_func : std::false_type {};
278template <
class T,
class Ret,
class... Args>
279struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)> : std::true_type {};
280template <
class T,
class Ret,
class... Args>
281struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &> : std::true_type {};
282template <
class T,
class Ret,
class... Args>
283struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&> : std::true_type {};
284template <
class T,
class Ret,
class... Args>
285struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile> : std::true_type {};
286template <
class T,
class Ret,
class... Args>
287struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &> : std::true_type {};
288template <
class T,
class Ret,
class... Args>
289struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &&> : std::true_type {};
292struct is_const_or_const_ref : std::false_type {};
294struct is_const_or_const_ref<T const &> : std::true_type {};
296struct is_const_or_const_ref<T const> : std::true_type {};
302 typename Fn,
typename... Args,
303#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
304 typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value && is_const_or_const_ref<Args...>::value)>,
306 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,
int = 0>
307constexpr auto invoke(Fn &&f, Args &&...args)
noexcept(
noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
308 ->
decltype(std::mem_fn(f)(std::forward<Args>(args)...))
310 return std::mem_fn(f)(std::forward<Args>(args)...);
313template <
typename Fn,
typename... Args,
typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
314constexpr auto invoke(Fn &&f, Args &&...args)
noexcept(
noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
315 ->
decltype(std::forward<Fn>(f)(std::forward<Args>(args)...))
317 return std::forward<Fn>(f)(std::forward<Args>(args)...);
321template <
class F,
class,
class... Us>
322struct invoke_result_impl;
324template <
class F,
class... Us>
325struct invoke_result_impl<F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()), Us...> {
326 using type =
decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
329template <
class F,
class... Us>
330using invoke_result = invoke_result_impl<F, void, Us...>;
332template <
class F,
class... Us>
333using invoke_result_t =
typename invoke_result<F, Us...>::type;
335#if defined(_MSC_VER) && _MSC_VER <= 1900
337template <
class T,
class U = T>
338struct is_swappable : std::true_type {};
340template <
class T,
class U = T>
341struct is_nothrow_swappable : std::true_type {};
344namespace swap_adl_tests {
351template <
class T, std::
size_t N>
352tag swap(T (&a)[N], T (&b)[N]);
356template <
class,
class>
357std::false_type can_swap(...) noexcept(false);
358template <class T, class U, class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>
359std::true_type can_swap(
int) noexcept(noexcept(swap(std::declval<T &>(), std::declval<U &>())));
361template <class, class>
362std::false_type uses_std(...);
363template <class T, class U>
364std::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag> uses_std(
int);
367struct is_std_swap_noexcept : std::integral_constant<
bool, std::is_nothrow_move_constructible<T>::value &&
368 std::is_nothrow_move_assignable<T>::value> {};
370template <
class T, std::
size_t N>
371struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
373template <
class T,
class U>
374struct is_adl_swap_noexcept : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
377template <
class T,
class U = T>
379 : std::integral_constant<bool, decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
380 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
381 (std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))> {
384template <
class T, std::
size_t N>
385struct is_swappable<T[N], T[N]>
386 : std::integral_constant<bool, decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
387 (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||
388 is_swappable<T, T>::value)> {};
390template <
class T,
class U = T>
391struct is_nothrow_swappable
392 : std::integral_constant<bool, is_swappable<T, U>::value &&
393 ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
394 detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
395 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
396 detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
403template <
class T,
class E>
408template <
class T,
class E,
class U>
409using expected_enable_forward_value =
410 detail::enable_if_t<std::is_constructible<T, U &&>::value && !std::is_same<detail::decay_t<U>,
in_place_t>::value &&
411 !std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
412 !std::is_same<unexpected<E>, detail::decay_t<U>>::value>;
414template <
class T,
class E,
class U,
class G,
class UR,
class GR>
415using expected_enable_from_other = detail::enable_if_t<
416 std::is_constructible<T, UR>::value && std::is_constructible<E, GR>::value &&
417 !std::is_constructible<T, expected<U, G> &>::value && !std::is_constructible<T, expected<U, G> &&>::value &&
418 !std::is_constructible<T, const expected<U, G> &>::value &&
419 !std::is_constructible<T, const expected<U, G> &&>::value && !std::is_convertible<expected<U, G> &, T>::value &&
420 !std::is_convertible<expected<U, G> &&, T>::value && !std::is_convertible<const expected<U, G> &, T>::value &&
421 !std::is_convertible<const expected<U, G> &&, T>::value>;
423template <
class T,
class U>
424using is_void_or = conditional_t<std::is_void<T>::value, std::true_type, U>;
427using is_copy_constructible_or_void = is_void_or<T, std::is_copy_constructible<T>>;
430using is_move_constructible_or_void = is_void_or<T, std::is_move_constructible<T>>;
433using is_copy_assignable_or_void = is_void_or<T, std::is_copy_assignable<T>>;
436using is_move_assignable_or_void = is_void_or<T, std::is_move_assignable<T>>;
450template <class T, class E, bool = std::is_trivially_destructible<T>::value,
451 bool = std::is_trivially_destructible<E>::value>
460 template <
class... Args, detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
nullptr>
465 template <
class U,
class... Args,
466 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
468 : m_val(il, std::forward<Args>(args)...), m_has_val(
true)
471 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
473 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
477 template <
class U,
class... Args,
478 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
480 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
489 m_unexpect.~unexpected<E>();
502template <
class T,
class E>
511 template <
class... Args, detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
nullptr>
516 template <
class U,
class... Args,
517 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
519 : m_val(il, std::forward<Args>(args)...), m_has_val(
true)
522 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
524 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
528 template <
class U,
class... Args,
529 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
531 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
545template <
class T,
class E>
554 template <
class... Args, detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
nullptr>
559 template <
class U,
class... Args,
560 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
562 : m_val(il, std::forward<Args>(args)...), m_has_val(
true)
565 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
567 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
571 template <
class U,
class... Args,
572 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
574 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
581 m_unexpect.~unexpected<E>();
594template <
class T,
class E>
603 template <
class... Args, detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
nullptr>
608 template <
class U,
class... Args,
609 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
611 : m_val(il, std::forward<Args>(args)...), m_has_val(
true)
614 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
616 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
620 template <
class U,
class... Args,
621 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
623 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
647 TL_EXPECTED_MSVC2015_CONSTEXPR
661 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
663 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
667 template <
class U,
class... Args,
668 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
670 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
697 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
699 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
703 template <
class U,
class... Args,
704 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
706 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
713 m_unexpect.~unexpected<E>();
726template <
class T,
class E>
730 template <
class... Args>
731 void construct(Args &&...args)
noexcept
733 new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
734 this->m_has_val =
true;
738 void construct_with(Rhs &&rhs)
noexcept
740 new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
741 this->m_has_val =
true;
744 template <
class... Args>
745 void construct_error(Args &&...args)
noexcept
747 new (std::addressof(this->m_unexpect))
unexpected<E>(std::forward<Args>(args)...);
748 this->m_has_val =
false;
751#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
759 template <class U = T, detail::enable_if_t<std::is_nothrow_copy_constructible<U>::value> * =
nullptr>
762 if (!this->m_has_val && rhs.m_has_val) {
763 geterr().~unexpected<E>();
764 construct(rhs.get());
772 template <class U = T, detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
773 std::is_nothrow_move_constructible<U>::value> * =
nullptr>
776 if (!this->m_has_val && rhs.m_has_val) {
778 geterr().~unexpected<E>();
779 construct(std::move(tmp));
790 template <class U = T, detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
791 !std::is_nothrow_move_constructible<U>::value> * =
nullptr>
794 if (!this->m_has_val && rhs.m_has_val) {
795 auto tmp = std::move(geterr());
796 geterr().~unexpected<E>();
798#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
800 construct(rhs.get());
802 geterr() = std::move(tmp);
806 construct(rhs.get());
814 template <class U = T, detail::enable_if_t<std::is_nothrow_move_constructible<U>::value> * =
nullptr>
817 if (!this->m_has_val && rhs.m_has_val) {
818 geterr().~unexpected<E>();
819 construct(std::move(rhs).get());
821 assign_common(std::move(rhs));
825 template <class U = T, detail::enable_if_t<!std::is_nothrow_move_constructible<U>::value> * =
nullptr>
828 if (!this->m_has_val && rhs.m_has_val) {
829 auto tmp = std::move(geterr());
830 geterr().~unexpected<E>();
831#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
833 construct(std::move(rhs).get());
835 geterr() = std::move(tmp);
839 construct(std::move(rhs).get());
842 assign_common(std::move(rhs));
851 if (!this->m_has_val && rhs.m_has_val) {
852 geterr().~unexpected<E>();
853 construct(rhs.get());
861 if (!this->m_has_val && rhs.m_has_val) {
862 geterr().~unexpected<E>();
863 construct(std::move(rhs).get());
865 assign_common(std::move(rhs));
873 void assign_common(Rhs &&rhs)
875 if (this->m_has_val) {
877 get() = std::forward<Rhs>(rhs).get();
880 construct_error(std::forward<Rhs>(rhs).geterr());
883 if (!rhs.m_has_val) {
884 geterr() = std::forward<Rhs>(rhs).geterr();
889 bool has_value()
const
891 return this->m_has_val;
894 TL_EXPECTED_11_CONSTEXPR T &get() &
898 constexpr const T &get()
const &
902 TL_EXPECTED_11_CONSTEXPR T &&get() &&
904 return std::move(this->m_val);
906#ifndef TL_EXPECTED_NO_CONSTRR
907 constexpr const T &&get()
const &&
909 return std::move(this->m_val);
915 return this->m_unexpect;
919 return this->m_unexpect;
923 return std::move(this->m_unexpect);
925#ifndef TL_EXPECTED_NO_CONSTRR
928 return std::move(this->m_unexpect);
932 TL_EXPECTED_11_CONSTEXPR
void destroy_val()
944 template <
class... Args>
945 void construct()
noexcept
947 this->m_has_val =
true;
953 void construct_with(Rhs &&)
noexcept
955 this->m_has_val =
true;
958 template <
class... Args>
959 void construct_error(Args &&...args)
noexcept
961 new (std::addressof(this->m_unexpect))
unexpected<E>(std::forward<Args>(args)...);
962 this->m_has_val =
false;
966 void assign(Rhs &&rhs)
noexcept
968 if (!this->m_has_val) {
970 geterr().~unexpected<E>();
973 geterr() = std::forward<Rhs>(rhs).geterr();
976 if (!rhs.m_has_val) {
977 construct_error(std::forward<Rhs>(rhs).geterr());
982 bool has_value()
const
984 return this->m_has_val;
989 return this->m_unexpect;
993 return this->m_unexpect;
997 return std::move(this->m_unexpect);
999#ifndef TL_EXPECTED_NO_CONSTRR
1002 return std::move(this->m_unexpect);
1006 TL_EXPECTED_11_CONSTEXPR
void destroy_val()
1014template <
class T,
class E,
1015 bool = is_void_or<T, TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::value &&
1016 TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>
1022template <
class T,
class E>
1029 if (rhs.has_value()) {
1030 this->construct_with(rhs);
1032 this->construct_error(rhs.geterr());
1046#ifndef TL_EXPECTED_GCC49
1047template <
class T,
class E,
1048 bool = is_void_or<T, std::is_trivially_move_constructible<T>>::value &&
1049 std::is_trivially_move_constructible<E>::value>
1054template <
class T,
class E,
bool = false>
1057template <
class T,
class E>
1067 if (rhs.has_value()) {
1068 this->construct_with(std::move(rhs));
1070 this->construct_error(std::move(rhs.geterr()));
1078template <
class T,
class E,
1079 bool = is_void_or<T,
conjunction<TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T),
1080 TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T),
1081 TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value &&
1082 TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value &&
1083 TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value &&
1084 TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>
1089template <
class T,
class E>
1110#ifndef TL_EXPECTED_GCC49
1111template <
class T,
class E,
1112 bool = is_void_or<T, conjunction<std::is_trivially_destructible<T>, std::is_trivially_move_constructible<T>,
1113 std::is_trivially_move_assignable<T>>>::value &&
1114 std::is_trivially_destructible<E>::value && std::is_trivially_move_constructible<E>::value &&
1115 std::is_trivially_move_assignable<E>::value>
1120template <
class T,
class E,
bool = false>
1124template <
class T,
class E>
1136 std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value)
1138 this->assign(std::move(rhs));
1145template <
class T,
class E,
1146 bool EnableCopy = (is_copy_constructible_or_void<T>::value && std::is_copy_constructible<E>::value),
1147 bool EnableMove = (is_move_constructible_or_void<T>::value && std::is_move_constructible<E>::value)>
1156template <
class T,
class E>
1165template <
class T,
class E>
1174template <
class T,
class E>
1186template <
class T,
class E,
1187 bool EnableCopy = (is_copy_constructible_or_void<T>::value && std::is_copy_constructible<E>::value &&
1188 is_copy_assignable_or_void<T>::value && std::is_copy_assignable<E>::value),
1189 bool EnableMove = (is_move_constructible_or_void<T>::value && std::is_move_constructible<E>::value &&
1190 is_move_assignable_or_void<T>::value && std::is_move_assignable<E>::value)>
1199template <
class T,
class E>
1208template <
class T,
class E>
1217template <
class T,
class E>
1235template <class T, class E, bool Enable = std::is_default_constructible<T>::value || std::is_void<T>::value>
1249template <
class T,
class E>
1270 virtual const char *what()
const noexcept override
1272 return "Bad expected access";
1275 const E &error()
const &
1283 const E &&error()
const &&
1285 return std::move(m_val);
1289 return std::move(m_val);
1303template <
class T,
class E>
1308 static_assert(!std::is_reference<T>::value,
"T must not be a reference");
1309 static_assert(!std::is_same<T, std::remove_cv<in_place_t>::type>::value,
"T must not be in_place_t");
1310 static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,
"T must not be unexpect_t");
1311 static_assert(!std::is_same<T, typename std::remove_cv<unexpected<E>>::type>::value,
"T must not be unexpected<E>");
1312 static_assert(!std::is_reference<E>::value,
"E must not be a reference");
1316 return std::addressof(this->m_val);
1318 const T *valptr()
const
1320 return std::addressof(this->m_val);
1324 return std::addressof(this->m_unexpect);
1328 return std::addressof(this->m_unexpect);
1331 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1332 TL_EXPECTED_11_CONSTEXPR U &val()
1338 return this->m_unexpect;
1341 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1342 constexpr const U &val()
const
1348 return this->m_unexpect;
1355 typedef T value_type;
1356 typedef E error_type;
1359#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
1360 !defined(TL_EXPECTED_GCC55)
1362 TL_EXPECTED_11_CONSTEXPR
auto and_then(F &&f) &
1364 return and_then_impl(*
this, std::forward<F>(f));
1367 TL_EXPECTED_11_CONSTEXPR
auto and_then(F &&f) &&
1369 return and_then_impl(std::move(*
this), std::forward<F>(f));
1372 constexpr auto and_then(F &&f)
const &
1374 return and_then_impl(*
this, std::forward<F>(f));
1377#ifndef TL_EXPECTED_NO_CONSTRR
1379 constexpr auto and_then(F &&f)
const &&
1381 return and_then_impl(std::move(*
this), std::forward<F>(f));
1387 TL_EXPECTED_11_CONSTEXPR
auto and_then(F &&f) & ->
decltype(and_then_impl(std::declval<expected &>(),
1388 std::forward<F>(f)))
1390 return and_then_impl(*
this, std::forward<F>(f));
1393 TL_EXPECTED_11_CONSTEXPR
auto and_then(F &&f) && ->
decltype(and_then_impl(std::declval<expected &&>(),
1394 std::forward<F>(f)))
1396 return and_then_impl(std::move(*
this), std::forward<F>(f));
1399 constexpr auto and_then(F &&f)
const & ->
decltype(and_then_impl(std::declval<expected const &>(),
1400 std::forward<F>(f)))
1402 return and_then_impl(*
this, std::forward<F>(f));
1405#ifndef TL_EXPECTED_NO_CONSTRR
1407 constexpr auto and_then(F &&f)
const && ->
decltype(and_then_impl(std::declval<expected const &&>(),
1408 std::forward<F>(f)))
1410 return and_then_impl(std::move(*
this), std::forward<F>(f));
1415#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
1416 !defined(TL_EXPECTED_GCC55)
1418 TL_EXPECTED_11_CONSTEXPR
auto map(F &&f) &
1420 return expected_map_impl(*
this, std::forward<F>(f));
1423 TL_EXPECTED_11_CONSTEXPR
auto map(F &&f) &&
1425 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1428 constexpr auto map(F &&f)
const &
1430 return expected_map_impl(*
this, std::forward<F>(f));
1433 constexpr auto map(F &&f)
const &&
1435 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1439 TL_EXPECTED_11_CONSTEXPR
decltype(expected_map_impl(std::declval<expected &>(), std::declval<F &&>())) map(F &&f) &
1441 return expected_map_impl(*
this, std::forward<F>(f));
1444 TL_EXPECTED_11_CONSTEXPR
decltype(expected_map_impl(std::declval<expected>(), std::declval<F &&>())) map(F &&f) &&
1446 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1449 constexpr decltype(expected_map_impl(std::declval<const expected &>(), std::declval<F &&>())) map(F &&f)
const &
1451 return expected_map_impl(*
this, std::forward<F>(f));
1454#ifndef TL_EXPECTED_NO_CONSTRR
1456 constexpr decltype(expected_map_impl(std::declval<const expected &&>(), std::declval<F &&>())) map(F &&f)
const &&
1458 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1463#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
1464 !defined(TL_EXPECTED_GCC55)
1466 TL_EXPECTED_11_CONSTEXPR
auto transform(F &&f) &
1468 return expected_map_impl(*
this, std::forward<F>(f));
1471 TL_EXPECTED_11_CONSTEXPR
auto transform(F &&f) &&
1473 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1476 constexpr auto transform(F &&f)
const &
1478 return expected_map_impl(*
this, std::forward<F>(f));
1481 constexpr auto transform(F &&f)
const &&
1483 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1487 TL_EXPECTED_11_CONSTEXPR
decltype(expected_map_impl(std::declval<expected &>(), std::declval<F &&>())) transform(
1490 return expected_map_impl(*
this, std::forward<F>(f));
1493 TL_EXPECTED_11_CONSTEXPR
decltype(expected_map_impl(std::declval<expected>(), std::declval<F &&>())) transform(
1496 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1499 constexpr decltype(expected_map_impl(std::declval<const expected &>(), std::declval<F &&>())) transform(
1502 return expected_map_impl(*
this, std::forward<F>(f));
1505#ifndef TL_EXPECTED_NO_CONSTRR
1507 constexpr decltype(expected_map_impl(std::declval<const expected &&>(), std::declval<F &&>())) transform(
1510 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1515#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
1516 !defined(TL_EXPECTED_GCC55)
1518 TL_EXPECTED_11_CONSTEXPR
auto map_error(F &&f) &
1520 return map_error_impl(*
this, std::forward<F>(f));
1523 TL_EXPECTED_11_CONSTEXPR
auto map_error(F &&f) &&
1525 return map_error_impl(std::move(*
this), std::forward<F>(f));
1528 constexpr auto map_error(F &&f)
const &
1530 return map_error_impl(*
this, std::forward<F>(f));
1533 constexpr auto map_error(F &&f)
const &&
1535 return map_error_impl(std::move(*
this), std::forward<F>(f));
1539 TL_EXPECTED_11_CONSTEXPR
decltype(map_error_impl(std::declval<expected &>(), std::declval<F &&>())) map_error(
1542 return map_error_impl(*
this, std::forward<F>(f));
1545 TL_EXPECTED_11_CONSTEXPR
decltype(map_error_impl(std::declval<expected &&>(), std::declval<F &&>())) map_error(
1548 return map_error_impl(std::move(*
this), std::forward<F>(f));
1551 constexpr decltype(map_error_impl(std::declval<const expected &>(), std::declval<F &&>())) map_error(F &&f)
const &
1553 return map_error_impl(*
this, std::forward<F>(f));
1556#ifndef TL_EXPECTED_NO_CONSTRR
1558 constexpr decltype(map_error_impl(std::declval<const expected &&>(), std::declval<F &&>())) map_error(
1561 return map_error_impl(std::move(*
this), std::forward<F>(f));
1565#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
1566 !defined(TL_EXPECTED_GCC55)
1568 TL_EXPECTED_11_CONSTEXPR
auto transform_error(F &&f) &
1570 return map_error_impl(*
this, std::forward<F>(f));
1573 TL_EXPECTED_11_CONSTEXPR
auto transform_error(F &&f) &&
1575 return map_error_impl(std::move(*
this), std::forward<F>(f));
1578 constexpr auto transform_error(F &&f)
const &
1580 return map_error_impl(*
this, std::forward<F>(f));
1583 constexpr auto transform_error(F &&f)
const &&
1585 return map_error_impl(std::move(*
this), std::forward<F>(f));
1589 TL_EXPECTED_11_CONSTEXPR
decltype(map_error_impl(std::declval<expected &>(), std::declval<F &&>())) transform_error(
1592 return map_error_impl(*
this, std::forward<F>(f));
1595 TL_EXPECTED_11_CONSTEXPR
decltype(map_error_impl(std::declval<expected &&>(), std::declval<F &&>()))
1596 transform_error(F &&f) &&
1598 return map_error_impl(std::move(*
this), std::forward<F>(f));
1601 constexpr decltype(map_error_impl(std::declval<const expected &>(), std::declval<F &&>())) transform_error(
1604 return map_error_impl(*
this, std::forward<F>(f));
1607#ifndef TL_EXPECTED_NO_CONSTRR
1609 constexpr decltype(map_error_impl(std::declval<const expected &&>(), std::declval<F &&>())) transform_error(
1612 return map_error_impl(std::move(*
this), std::forward<F>(f));
1617 expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) &
1619 return or_else_impl(*
this, std::forward<F>(f));
1623 expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) &&
1625 return or_else_impl(std::move(*
this), std::forward<F>(f));
1629 expected constexpr or_else(F &&f)
const &
1631 return or_else_impl(*
this, std::forward<F>(f));
1634#ifndef TL_EXPECTED_NO_CONSTRR
1636 expected constexpr or_else(F &&f)
const &&
1638 return or_else_impl(std::move(*
this), std::forward<F>(f));
1647 template <
class... Args, detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
nullptr>
1653 template <
class U,
class... Args,
1654 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1660 template <class G = E, detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
nullptr,
1661 detail::enable_if_t<!std::is_convertible<const G &, E>::value> * =
nullptr>
1667 template <class G = E, detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
nullptr,
1668 detail::enable_if_t<std::is_convertible<const G &, E>::value> * =
nullptr>
1674 template <class G = E, detail::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1675 detail::enable_if_t<!std::is_convertible<G &&, E>::value> * =
nullptr>
1676 explicit constexpr expected(
unexpected<G> &&e)
noexcept(std::is_nothrow_constructible<E, G &&>::value)
1681 template <class G = E, detail::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1682 detail::enable_if_t<std::is_convertible<G &&, E>::value> * =
nullptr>
1688 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
1694 template <
class U,
class... Args,
1695 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1701 template <
class U,
class G,
1702 detail::enable_if_t<!(std::is_convertible<U const &, T>::value &&
1703 std::is_convertible<G const &, E>::value)> * =
nullptr,
1704 detail::expected_enable_from_other<T, E, U, G, const U &, const G &> * =
nullptr>
1707 if (rhs.has_value()) {
1708 this->construct(*rhs);
1710 this->construct_error(rhs.error());
1714 template <
class U,
class G,
1715 detail::enable_if_t<(std::is_convertible<U const &, T>::value &&
1716 std::is_convertible<G const &, E>::value)> * =
nullptr,
1717 detail::expected_enable_from_other<T, E, U, G, const U &, const G &> * =
nullptr>
1720 if (rhs.has_value()) {
1721 this->construct(*rhs);
1723 this->construct_error(rhs.error());
1729 detail::enable_if_t<!(std::is_convertible<U &&, T>::value && std::is_convertible<G &&, E>::value)> * =
nullptr,
1730 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1733 if (rhs.has_value()) {
1734 this->construct(std::move(*rhs));
1736 this->construct_error(std::move(rhs.error()));
1742 detail::enable_if_t<(std::is_convertible<U &&, T>::value && std::is_convertible<G &&, E>::value)> * =
nullptr,
1743 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1746 if (rhs.has_value()) {
1747 this->construct(std::move(*rhs));
1749 this->construct_error(std::move(rhs.error()));
1753 template <class U = T, detail::enable_if_t<!std::is_convertible<U &&, T>::value> * =
nullptr,
1754 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1755 explicit TL_EXPECTED_MSVC2015_CONSTEXPR
expected(U &&v) :
expected(in_place, std::forward<U>(v))
1759 template <class U = T, detail::enable_if_t<std::is_convertible<U &&, T>::value> * =
nullptr,
1760 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1761 TL_EXPECTED_MSVC2015_CONSTEXPR
expected(U &&v) :
expected(in_place, std::forward<U>(v))
1766 class U = T,
class G = T, detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
nullptr,
1767 detail::enable_if_t<!std::is_void<G>::value> * =
nullptr,
1768 detail::enable_if_t<(!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1770 std::is_constructible<T, U>::value && std::is_assignable<G &, U>::value &&
1771 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1775 val() = std::forward<U>(v);
1777 err().~unexpected<E>();
1778 ::new (valptr()) T(std::forward<U>(v));
1779 this->m_has_val =
true;
1786 class U = T,
class G = T, detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =
nullptr,
1787 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr,
1788 detail::enable_if_t<(!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1790 std::is_constructible<T, U>::value && std::is_assignable<G &, U>::value &&
1791 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1795 val() = std::forward<U>(v);
1797 auto tmp = std::move(err());
1798 err().~unexpected<E>();
1800#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1802 ::new (valptr()) T(std::forward<U>(v));
1803 this->m_has_val =
true;
1805 err() = std::move(tmp);
1809 ::new (valptr()) T(std::forward<U>(v));
1810 this->m_has_val =
true;
1817 template <class G = E, detail::enable_if_t<std::is_nothrow_copy_constructible<G>::value &&
1818 std::is_assignable<G &, G>::value> * =
nullptr>
1824 this->destroy_val();
1826 this->m_has_val =
false;
1832 template <class G = E, detail::enable_if_t<std::is_nothrow_move_constructible<G>::value &&
1833 std::is_move_assignable<G>::value> * =
nullptr>
1837 err() = std::move(rhs);
1839 this->destroy_val();
1841 this->m_has_val =
false;
1847 template <
class... Args, detail::enable_if_t<std::is_nothrow_constructible<T, Args &&...>::value> * =
nullptr>
1848 void emplace(Args &&...args)
1853 err().~unexpected<E>();
1854 this->m_has_val =
true;
1856 ::new (valptr()) T(std::forward<Args>(args)...);
1859 template <
class... Args, detail::enable_if_t<!std::is_nothrow_constructible<T, Args &&...>::value> * =
nullptr>
1860 void emplace(Args &&...args)
1864 ::new (valptr()) T(std::forward<Args>(args)...);
1866 auto tmp = std::move(err());
1867 err().~unexpected<E>();
1869#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1871 ::new (valptr()) T(std::forward<Args>(args)...);
1872 this->m_has_val =
true;
1874 err() = std::move(tmp);
1878 ::new (valptr()) T(std::forward<Args>(args)...);
1879 this->m_has_val =
true;
1884 template <
class U,
class... Args,
1885 detail::enable_if_t<std::is_nothrow_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
1887 void emplace(std::initializer_list<U> il, Args &&...args)
1890 T t(il, std::forward<Args>(args)...);
1891 val() = std::move(t);
1893 err().~unexpected<E>();
1894 ::new (valptr()) T(il, std::forward<Args>(args)...);
1895 this->m_has_val =
true;
1899 template <
class U,
class... Args,
1900 detail::enable_if_t<!std::is_nothrow_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
1902 void emplace(std::initializer_list<U> il, Args &&...args)
1905 T t(il, std::forward<Args>(args)...);
1906 val() = std::move(t);
1908 auto tmp = std::move(err());
1909 err().~unexpected<E>();
1911#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1913 ::new (valptr()) T(il, std::forward<Args>(args)...);
1914 this->m_has_val =
true;
1916 err() = std::move(tmp);
1920 ::new (valptr()) T(il, std::forward<Args>(args)...);
1921 this->m_has_val =
true;
1927 using t_is_void = std::true_type;
1928 using t_is_not_void = std::false_type;
1929 using t_is_nothrow_move_constructible = std::true_type;
1930 using move_constructing_t_can_throw = std::false_type;
1931 using e_is_nothrow_move_constructible = std::true_type;
1932 using move_constructing_e_can_throw = std::false_type;
1934 void swap_where_both_have_value(
expected & , t_is_void)
noexcept
1939 void swap_where_both_have_value(
expected &rhs, t_is_not_void)
1942 swap(val(), rhs.val());
1945 void swap_where_only_one_has_value(
expected &rhs, t_is_void)
noexcept(std::is_nothrow_move_constructible<E>::value)
1948 rhs.err().~unexpected_type();
1949 std::swap(this->m_has_val, rhs.m_has_val);
1952 void swap_where_only_one_has_value(
expected &rhs, t_is_not_void)
1954 swap_where_only_one_has_value_and_t_is_not_void(rhs,
typename std::is_nothrow_move_constructible<T>::type{},
1955 typename std::is_nothrow_move_constructible<E>::type{});
1958 void swap_where_only_one_has_value_and_t_is_not_void(
expected &rhs, t_is_nothrow_move_constructible,
1959 e_is_nothrow_move_constructible)
noexcept
1961 auto temp = std::move(val());
1964 rhs.err().~unexpected_type();
1965 ::new (rhs.valptr()) T(std::move(temp));
1966 std::swap(this->m_has_val, rhs.m_has_val);
1969 void swap_where_only_one_has_value_and_t_is_not_void(
expected &rhs, t_is_nothrow_move_constructible,
1970 move_constructing_e_can_throw)
1972 auto temp = std::move(val());
1974#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1977 rhs.err().~unexpected_type();
1978 ::new (rhs.valptr()) T(std::move(temp));
1979 std::swap(this->m_has_val, rhs.m_has_val);
1981 val() = std::move(temp);
1986 rhs.err().~unexpected_type();
1987 ::new (rhs.valptr()) T(std::move(temp));
1988 std::swap(this->m_has_val, rhs.m_has_val);
1992 void swap_where_only_one_has_value_and_t_is_not_void(
expected &rhs, move_constructing_t_can_throw,
1993 e_is_nothrow_move_constructible)
1995 auto temp = std::move(rhs.err());
1996 rhs.err().~unexpected_type();
1997#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1999 ::new (rhs.valptr()) T(std::move(val()));
2002 std::swap(this->m_has_val, rhs.m_has_val);
2004 rhs.err() = std::move(temp);
2008 ::new (rhs.valptr()) T(std::move(val()));
2011 std::swap(this->m_has_val, rhs.m_has_val);
2016 template <
class OT = T,
class OE = E>
2018 (std::is_nothrow_move_constructible<OT>::value ||
2019 std::is_nothrow_move_constructible<OE>::value)>
2020 swap(
expected &rhs)
noexcept(std::is_nothrow_move_constructible<T>::value &&
2024 if (has_value() && rhs.has_value()) {
2025 swap_where_both_have_value(rhs,
typename std::is_void<T>::type{});
2026 }
else if (!has_value() && rhs.has_value()) {
2028 }
else if (has_value()) {
2029 swap_where_only_one_has_value(rhs,
typename std::is_void<T>::type{});
2032 swap(err(), rhs.err());
2036 constexpr const T *operator->()
const
2038 TL_ASSERT(has_value());
2041 TL_EXPECTED_11_CONSTEXPR T *operator->()
2043 TL_ASSERT(has_value());
2047 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2048 constexpr const U &operator*()
const &
2050 TL_ASSERT(has_value());
2053 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2054 TL_EXPECTED_11_CONSTEXPR U &operator*() &
2056 TL_ASSERT(has_value());
2059 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2060 constexpr const U &&operator*()
const &&
2062 TL_ASSERT(has_value());
2063 return std::move(val());
2065 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2066 TL_EXPECTED_11_CONSTEXPR U &&operator*() &&
2068 TL_ASSERT(has_value());
2069 return std::move(val());
2071 constexpr bool has_value()
const noexcept
2073 return this->m_has_val;
2075 constexpr bool has_error()
const noexcept
2077 return !(this->has_value());
2079 constexpr explicit operator bool()
const noexcept
2081 return this->m_has_val;
2084 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2085 TL_EXPECTED_11_CONSTEXPR
const U &value()
const &
2090 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2091 TL_EXPECTED_11_CONSTEXPR U &value() &
2096 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2097 TL_EXPECTED_11_CONSTEXPR
const U &&value()
const &&
2100 return std::move(val());
2102 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2103 TL_EXPECTED_11_CONSTEXPR U &&value() &&
2106 return std::move(val());
2109 constexpr const E &error()
const &
2111 TL_ASSERT(!has_value());
2112 return err().value();
2114 TL_EXPECTED_11_CONSTEXPR E &error() &
2116 TL_ASSERT(!has_value());
2117 return err().value();
2119 constexpr const E &&error()
const &&
2121 TL_ASSERT(!has_value());
2122 return std::move(err().value());
2124 TL_EXPECTED_11_CONSTEXPR E &&error() &&
2126 TL_ASSERT(!has_value());
2127 return std::move(err().value());
2131 constexpr T value_or(U &&v)
const &
2133 static_assert(std::is_copy_constructible<T>::value && std::is_convertible<U &&, T>::value,
2134 "T must be copy-constructible and convertible to from U&&");
2135 return bool(*
this) ? **this :
static_cast<T
>(std::forward<U>(v));
2138 TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) &&
2140 static_assert(std::is_move_constructible<T>::value && std::is_convertible<U &&, T>::value,
2141 "T must be move-constructible and convertible to from U&&");
2142 return bool(*
this) ? std::move(**
this) :
static_cast<T
>(std::forward<U>(v));
2146 template <
class G = E>
2147 constexpr E error_or(G &&e)
const &
2149 static_assert(std::is_copy_constructible<E>::value && std::is_convertible<G, E>::value,
2150 "E must be copy-constructible and convertible to from G&&");
2151 return has_value() ? std::forward<G>(e) : error();
2153 template <
class G = E>
2154 TL_EXPECTED_11_CONSTEXPR E error_or(G &&e) &&
2156 static_assert(std::is_move_constructible<E>::value && std::is_convertible<G, E>::value,
2157 "E must be move-constructible and convertible to from G&&");
2158 return has_value() ? std::forward<G>(e) : std::move(error());
2164using exp_t =
typename detail::decay_t<Exp>::value_type;
2166using err_t =
typename detail::decay_t<Exp>::error_type;
2167template <
class Exp,
class Ret>
2170#ifdef TL_EXPECTED_CXX14
2171template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2172 class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>()))>
2173constexpr auto and_then_impl(Exp &&exp, F &&f)
2177 return exp.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
2178 : Ret(unexpect, std::forward<Exp>(exp).error());
2181template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2182 class Ret = decltype(detail::invoke(std::declval<F>()))>
2183constexpr auto and_then_impl(Exp &&exp, F &&f)
2185 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
2187 return exp.has_value() ? detail::invoke(std::forward<F>(f)) : Ret(unexpect, std::forward<Exp>(exp).error());
2192template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>())),
2193 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr>
2194auto and_then_impl(Exp &&exp, F &&f) -> Ret
2198 return exp.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
2199 : Ret(unexpect, std::forward<Exp>(exp).error());
2202template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>())),
2203 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr>
2204constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret
2208 return exp.has_value() ? detail::invoke(std::forward<F>(f)) : Ret(unexpect, std::forward<Exp>(exp).error());
2212#ifdef TL_EXPECTED_CXX14
2213template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2214 class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>())),
2215 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2216constexpr auto expected_map_impl(Exp &&exp, F &&f)
2218 using result = ret_t<Exp, detail::decay_t<Ret>>;
2219 return exp.has_value() ? result(detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp)))
2220 : result(unexpect, std::forward<Exp>(exp).error());
2223template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2224 class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>())),
2225 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2226auto expected_map_impl(Exp &&exp, F &&f)
2228 using result = expected<void, err_t<Exp>>;
2229 if (exp.has_value()) {
2230 detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2234 return result(unexpect, std::forward<Exp>(exp).error());
2237template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2238 class Ret = decltype(detail::invoke(std::declval<F>())),
2239 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2240constexpr auto expected_map_impl(Exp &&exp, F &&f)
2242 using result = ret_t<Exp, detail::decay_t<Ret>>;
2243 return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
2244 : result(unexpect, std::forward<Exp>(exp).error());
2247template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2248 class Ret = decltype(detail::invoke(std::declval<F>())),
2249 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2250auto expected_map_impl(Exp &&exp, F &&f)
2252 using result = expected<void, err_t<Exp>>;
2253 if (exp.has_value()) {
2254 detail::invoke(std::forward<F>(f));
2258 return result(unexpect, std::forward<Exp>(exp).error());
2261template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2262 class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>())),
2263 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2265constexpr auto expected_map_impl(Exp &&exp, F &&f) -> ret_t<Exp, detail::decay_t<Ret>>
2267 using result = ret_t<Exp, detail::decay_t<Ret>>;
2269 return exp.has_value() ? result(detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp)))
2270 : result(unexpect, std::forward<Exp>(exp).error());
2273template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2274 class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>())),
2275 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2277auto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>>
2279 if (exp.has_value()) {
2280 detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2284 return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
2287template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2288 class Ret = decltype(detail::invoke(std::declval<F>())),
2289 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2291constexpr auto expected_map_impl(Exp &&exp, F &&f) -> ret_t<Exp, detail::decay_t<Ret>>
2293 using result = ret_t<Exp, detail::decay_t<Ret>>;
2295 return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
2296 : result(unexpect, std::forward<Exp>(exp).error());
2299template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2300 class Ret = decltype(detail::invoke(std::declval<F>())),
2301 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2303auto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>>
2305 if (exp.has_value()) {
2306 detail::invoke(std::forward<F>(f));
2310 return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
2314#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
2315 !defined(TL_EXPECTED_GCC55)
2316template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2317 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2318 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2319constexpr auto map_error_impl(Exp &&exp, F &&f)
2321 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2322 return exp.has_value() ? result(*std::forward<Exp>(exp))
2323 : result(unexpect, detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()));
2325template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2326 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2327 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2328auto map_error_impl(Exp &&exp, F &&f)
2330 using result = expected<exp_t<Exp>, monostate>;
2331 if (exp.has_value()) {
2332 return result(*std::forward<Exp>(exp));
2335 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2336 return result(unexpect, monostate{});
2338template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2339 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2340 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2341constexpr auto map_error_impl(Exp &&exp, F &&f)
2343 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2344 return exp.has_value() ? result()
2345 : result(unexpect, detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()));
2347template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2348 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2349 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2350auto map_error_impl(Exp &&exp, F &&f)
2352 using result = expected<exp_t<Exp>, monostate>;
2353 if (exp.has_value()) {
2357 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2358 return result(unexpect, monostate{});
2361template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2362 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2363 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2364constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, detail::decay_t<Ret>>
2366 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2368 return exp.has_value() ? result(*std::forward<Exp>(exp))
2369 : result(unexpect, detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()));
2372template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2373 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2374 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2375auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate>
2377 using result = expected<exp_t<Exp>, monostate>;
2378 if (exp.has_value()) {
2379 return result(*std::forward<Exp>(exp));
2382 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2383 return result(unexpect, monostate{});
2386template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2387 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2388 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2389constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, detail::decay_t<Ret>>
2391 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2393 return exp.has_value() ? result()
2394 : result(unexpect, detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()));
2397template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2398 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2399 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2400auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate>
2402 using result = expected<exp_t<Exp>, monostate>;
2403 if (exp.has_value()) {
2407 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2408 return result(unexpect, monostate{});
2412#ifdef TL_EXPECTED_CXX14
2413template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2414 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2415constexpr auto or_else_impl(Exp &&exp, F &&f)
2417 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
2418 return exp.has_value() ? std::forward<Exp>(exp)
2419 : detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2422template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2423 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2424detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f)
2426 return exp.has_value()
2427 ? std::forward<Exp>(exp)
2428 : (detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()), std::forward<Exp>(exp));
2431template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2432 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2433auto or_else_impl(Exp &&exp, F &&f) -> Ret
2435 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
2436 return exp.has_value() ? std::forward<Exp>(exp)
2437 : detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2440template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2441 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2442detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f)
2444 return exp.has_value()
2445 ? std::forward<Exp>(exp)
2446 : (detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()), std::forward<Exp>(exp));
2451template <
class T,
class E,
class U,
class F>
2452constexpr bool operator==(
const expected<T, E> &lhs,
const expected<U, F> &rhs)
2454 return (lhs.has_value() != rhs.has_value()) ? false
2455 : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
2457template <
class T,
class E,
class U,
class F>
2458constexpr bool operator!=(
const expected<T, E> &lhs,
const expected<U, F> &rhs)
2460 return (lhs.has_value() != rhs.has_value()) ? true : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);
2462template <
class E,
class F>
2463constexpr bool operator==(
const expected<void, E> &lhs,
const expected<void, F> &rhs)
2465 return (lhs.has_value() != rhs.has_value()) ? false : (!lhs.has_value() ? lhs.error() == rhs.error() :
true);
2467template <
class E,
class F>
2468constexpr bool operator!=(
const expected<void, E> &lhs,
const expected<void, F> &rhs)
2470 return (lhs.has_value() != rhs.has_value()) ? true : (!lhs.has_value() ? lhs.error() == rhs.error() :
false);
2473template <
class T,
class E,
class U>
2474constexpr bool operator==(
const expected<T, E> &x,
const U &v)
2476 return x.has_value() ? *x == v :
false;
2478template <
class T,
class E,
class U>
2479constexpr bool operator==(
const U &v,
const expected<T, E> &x)
2481 return x.has_value() ? *x == v :
false;
2483template <
class T,
class E,
class U>
2484constexpr bool operator!=(
const expected<T, E> &x,
const U &v)
2486 return x.has_value() ? *x != v :
true;
2488template <
class T,
class E,
class U>
2489constexpr bool operator!=(
const U &v,
const expected<T, E> &x)
2491 return x.has_value() ? *x != v :
true;
2494template <
class T,
class E>
2495constexpr bool operator==(
const expected<T, E> &x,
const unexpected<E> &e)
2497 return x.has_value() ? false : x.error() == e.value();
2499template <
class T,
class E>
2500constexpr bool operator==(
const unexpected<E> &e,
const expected<T, E> &x)
2502 return x.has_value() ? false : x.error() == e.value();
2504template <
class T,
class E>
2505constexpr bool operator!=(
const expected<T, E> &x,
const unexpected<E> &e)
2507 return x.has_value() ? true : x.error() != e.value();
2509template <
class T,
class E>
2510constexpr bool operator!=(
const unexpected<E> &e,
const expected<T, E> &x)
2512 return x.has_value() ? true : x.error() != e.value();
2515template <
class T,
class E,
2516 detail::enable_if_t<(std::is_void<T>::value || std::is_move_constructible<T>::value) &&
2517 detail::is_swappable<T>::value && std::is_move_constructible<E>::value &&
2518 detail::is_swappable<E>::value> * =
nullptr>
2519void swap(expected<T, E> &lhs, expected<T, E> &rhs)
noexcept(
noexcept(lhs.swap(rhs)))
Definition expected.hpp:1264
Definition expected.hpp:1307
Definition expected.hpp:138
Top level namespace of M5.
Definition base64.cpp:39
STL compatibility functions and classes.
Definition expected.hpp:2191
Definition optional.hpp:132
Definition expected.hpp:1228
Definition expected.hpp:1085
Definition expected.hpp:1017
Definition expected.hpp:1236
Definition expected.hpp:1191
Definition expected.hpp:1148
Definition expected.hpp:1116
Definition expected.hpp:1050
Definition expected.hpp:727
Definition expected.hpp:675
Definition expected.hpp:452
Definition expected.hpp:402
Definition optional.hpp:266
Definition optional.hpp:251
Definition expected.hpp:441
A tag type to tell optional to construct its value in-place.
Definition optional.hpp:105
Definition expected.hpp:225