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)
56#if (__cplusplus > 201103L) && !defined(TL_EXPECTED_GCC49)
58#define TL_ASSERT(x) assert(x)
64#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
67#define TL_EXPECTED_NO_CONSTRR
69#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor<T>
70#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>
73#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>
77#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
78#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
79#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
84struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T> {};
86template <
class T,
class A>
87struct is_trivially_copy_constructible<std::vector<T, A>> : std::false_type {};
94#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) stl::detail::is_trivially_copy_constructible<T>
95#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>
96#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>
98#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible<T>
99#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>
100#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>
103#if __cplusplus > 201103L
104#define TL_EXPECTED_CXX14
107#ifdef TL_EXPECTED_GCC49
108#define TL_EXPECTED_GCC49_CONSTEXPR
110#define TL_EXPECTED_GCC49_CONSTEXPR constexpr
113#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || defined(TL_EXPECTED_GCC49))
114#define TL_EXPECTED_11_CONSTEXPR
116#define TL_EXPECTED_11_CONSTEXPR constexpr
121template <
class T,
class E>
124#ifndef TL_MONOSTATE_INPLACE_MUTEX
125#define TL_MONOSTATE_INPLACE_MUTEX
129 explicit in_place_t() =
default;
131static constexpr in_place_t in_place{};
137 static_assert(!std::is_same<E, void>::value,
"E must not be void");
140 constexpr explicit unexpected(
const E &e) : m_val(e)
144 constexpr explicit unexpected(E &&e) : m_val(std::move(e))
148 template <
class... Args,
typename std::enable_if<std::is_constructible<E, Args &&...>::value>::type * =
nullptr>
149 constexpr explicit unexpected(Args &&...args) : m_val(std::forward<Args>(args)...)
152 template <
class U,
class... Args,
153 typename std::enable_if<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value>::type * =
155 constexpr explicit unexpected(std::initializer_list<U> l, Args &&...args) : m_val(l, std::forward<Args>(args)...)
159 constexpr const E &value()
const &
163 TL_EXPECTED_11_CONSTEXPR E &value() &
167 TL_EXPECTED_11_CONSTEXPR E &&value() &&
169 return std::move(m_val);
171 constexpr const E &&value()
const &&
173 return std::move(m_val);
180#ifdef __cpp_deduction_guides
188 return lhs.value() == rhs.value();
191constexpr bool operator!=(
const unexpected<E> &lhs,
const unexpected<E> &rhs)
193 return lhs.value() != rhs.value();
196constexpr bool operator<(
const unexpected<E> &lhs,
const unexpected<E> &rhs)
198 return lhs.value() < rhs.value();
201constexpr bool operator<=(
const unexpected<E> &lhs,
const unexpected<E> &rhs)
203 return lhs.value() <= rhs.value();
206constexpr bool operator>(
const unexpected<E> &lhs,
const unexpected<E> &rhs)
208 return lhs.value() > rhs.value();
211constexpr bool operator>=(
const unexpected<E> &lhs,
const unexpected<E> &rhs)
213 return lhs.value() >= rhs.value();
217unexpected<typename std::decay<E>::type> make_unexpected(E &&e)
219 return unexpected<typename std::decay<E>::type>(std::forward<E>(e));
229[[noreturn]] TL_EXPECTED_11_CONSTEXPR
void throw_exception(E &&e)
231#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
232 throw std::forward<E>(e);
238 __builtin_unreachable();
243#ifndef TL_TRAITS_MUTEX
244#define TL_TRAITS_MUTEX
247using remove_const_t =
typename std::remove_const<T>::type;
249using remove_reference_t =
typename std::remove_reference<T>::type;
251using decay_t =
typename std::decay<T>::type;
252template <
bool E,
class T =
void>
253using enable_if_t =
typename std::enable_if<E, T>::type;
254template <
bool B,
class T,
class F>
255using conditional_t =
typename std::conditional<B, T, F>::type;
259struct conjunction : std::true_type {};
261struct conjunction<B> : B {};
262template <
class B,
class... Bs>
263struct conjunction<B, Bs...> : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
265#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
266#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
272#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
274struct is_pointer_to_non_const_member_func : std::false_type {};
275template <
class T,
class Ret,
class... Args>
276struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)> : std::true_type {};
277template <
class T,
class Ret,
class... Args>
278struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &> : std::true_type {};
279template <
class T,
class Ret,
class... Args>
280struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&> : std::true_type {};
281template <
class T,
class Ret,
class... Args>
282struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile> : std::true_type {};
283template <
class T,
class Ret,
class... Args>
284struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &> : std::true_type {};
285template <
class T,
class Ret,
class... Args>
286struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &&> : std::true_type {};
289struct is_const_or_const_ref : std::false_type {};
291struct is_const_or_const_ref<T const &> : std::true_type {};
293struct is_const_or_const_ref<T const> : std::true_type {};
299 typename Fn,
typename... Args,
300#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
301 typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value && is_const_or_const_ref<Args...>::value)>,
303 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,
int = 0>
304constexpr auto invoke(Fn &&f, Args &&...args)
noexcept(
noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
305 ->
decltype(std::mem_fn(f)(std::forward<Args>(args)...))
307 return std::mem_fn(f)(std::forward<Args>(args)...);
310template <
typename Fn,
typename... Args,
typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
311constexpr auto invoke(Fn &&f, Args &&...args)
noexcept(
noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
312 ->
decltype(std::forward<Fn>(f)(std::forward<Args>(args)...))
314 return std::forward<Fn>(f)(std::forward<Args>(args)...);
318template <
class F,
class,
class... Us>
319struct invoke_result_impl;
321template <
class F,
class... Us>
322struct invoke_result_impl<F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()), Us...> {
323 using type =
decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
326template <
class F,
class... Us>
327using invoke_result = invoke_result_impl<F, void, Us...>;
329template <
class F,
class... Us>
330using invoke_result_t =
typename invoke_result<F, Us...>::type;
332#if defined(_MSC_VER) && _MSC_VER <= 1900
334template <
class T,
class U = T>
335struct is_swappable : std::true_type {};
337template <
class T,
class U = T>
338struct is_nothrow_swappable : std::true_type {};
341namespace swap_adl_tests {
348template <
class T, std::
size_t N>
349tag swap(T (&a)[N], T (&b)[N]);
353template <
class,
class>
354std::false_type can_swap(...) noexcept(false);
355template <class T, class U, class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>
356std::true_type can_swap(
int) noexcept(noexcept(swap(std::declval<T &>(), std::declval<U &>())));
358template <class, class>
359std::false_type uses_std(...);
360template <class T, class U>
361std::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag> uses_std(
int);
364struct is_std_swap_noexcept : std::integral_constant<
bool, std::is_nothrow_move_constructible<T>::value &&
365 std::is_nothrow_move_assignable<T>::value> {};
367template <
class T, std::
size_t N>
368struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
370template <
class T,
class U>
371struct is_adl_swap_noexcept : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
374template <
class T,
class U = T>
376 : std::integral_constant<bool, decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
377 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
378 (std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))> {
381template <
class T, std::
size_t N>
382struct is_swappable<T[N], T[N]>
383 : std::integral_constant<bool, decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
384 (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||
385 is_swappable<T, T>::value)> {};
387template <
class T,
class U = T>
388struct is_nothrow_swappable
389 : std::integral_constant<bool, is_swappable<T, U>::value &&
390 ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
391 detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
392 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
393 detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
400template <
class T,
class E>
405template <
class T,
class E,
class U>
406using expected_enable_forward_value =
407 detail::enable_if_t<std::is_constructible<T, U &&>::value && !std::is_same<detail::decay_t<U>,
in_place_t>::value &&
408 !std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
409 !std::is_same<unexpected<E>, detail::decay_t<U>>::value>;
411template <
class T,
class E,
class U,
class G,
class UR,
class GR>
412using expected_enable_from_other = detail::enable_if_t<
413 std::is_constructible<T, UR>::value && std::is_constructible<E, GR>::value &&
414 !std::is_constructible<T, expected<U, G> &>::value && !std::is_constructible<T, expected<U, G> &&>::value &&
415 !std::is_constructible<T, const expected<U, G> &>::value &&
416 !std::is_constructible<T, const expected<U, G> &&>::value && !std::is_convertible<expected<U, G> &, T>::value &&
417 !std::is_convertible<expected<U, G> &&, T>::value && !std::is_convertible<const expected<U, G> &, T>::value &&
418 !std::is_convertible<const expected<U, G> &&, T>::value>;
420template <
class T,
class U>
421using is_void_or = conditional_t<std::is_void<T>::value, std::true_type, U>;
424using is_copy_constructible_or_void = is_void_or<T, std::is_copy_constructible<T>>;
427using is_move_constructible_or_void = is_void_or<T, std::is_move_constructible<T>>;
430using is_copy_assignable_or_void = is_void_or<T, std::is_copy_assignable<T>>;
433using is_move_assignable_or_void = is_void_or<T, std::is_move_assignable<T>>;
447template <class T, class E, bool = std::is_trivially_destructible<T>::value,
448 bool = std::is_trivially_destructible<E>::value>
457 template <
class... Args, detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
nullptr>
462 template <
class U,
class... Args,
463 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
465 : m_val(il, std::forward<Args>(args)...), m_has_val(
true)
468 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
470 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
474 template <
class U,
class... Args,
475 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
477 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
486 m_unexpect.~unexpected<E>();
499template <
class T,
class E>
508 template <
class... Args, detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
nullptr>
513 template <
class U,
class... Args,
514 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
516 : m_val(il, std::forward<Args>(args)...), m_has_val(
true)
519 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
521 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
525 template <
class U,
class... Args,
526 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
528 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
542template <
class T,
class E>
551 template <
class... Args, detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
nullptr>
556 template <
class U,
class... Args,
557 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
559 : m_val(il, std::forward<Args>(args)...), m_has_val(
true)
562 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
564 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
568 template <
class U,
class... Args,
569 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
571 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
578 m_unexpect.~unexpected<E>();
591template <
class T,
class E>
600 template <
class... Args, detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
nullptr>
605 template <
class U,
class... Args,
606 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
608 : m_val(il, std::forward<Args>(args)...), m_has_val(
true)
611 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
613 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
617 template <
class U,
class... Args,
618 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
620 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
644 TL_EXPECTED_MSVC2015_CONSTEXPR
658 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
660 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
664 template <
class U,
class... Args,
665 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
667 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
694 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
696 : m_unexpect(std::forward<Args>(args)...), m_has_val(
false)
700 template <
class U,
class... Args,
701 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
703 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(
false)
710 m_unexpect.~unexpected<E>();
723template <
class T,
class E>
727 template <
class... Args>
728 void construct(Args &&...args)
noexcept
730 new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
731 this->m_has_val =
true;
735 void construct_with(Rhs &&rhs)
noexcept
737 new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
738 this->m_has_val =
true;
741 template <
class... Args>
742 void construct_error(Args &&...args)
noexcept
744 new (std::addressof(this->m_unexpect))
unexpected<E>(std::forward<Args>(args)...);
745 this->m_has_val =
false;
748#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
756 template <class U = T, detail::enable_if_t<std::is_nothrow_copy_constructible<U>::value> * =
nullptr>
759 if (!this->m_has_val && rhs.m_has_val) {
760 geterr().~unexpected<E>();
761 construct(rhs.get());
769 template <class U = T, detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
770 std::is_nothrow_move_constructible<U>::value> * =
nullptr>
773 if (!this->m_has_val && rhs.m_has_val) {
775 geterr().~unexpected<E>();
776 construct(std::move(tmp));
787 template <class U = T, detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
788 !std::is_nothrow_move_constructible<U>::value> * =
nullptr>
791 if (!this->m_has_val && rhs.m_has_val) {
792 auto tmp = std::move(geterr());
793 geterr().~unexpected<E>();
795#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
797 construct(rhs.get());
799 geterr() = std::move(tmp);
803 construct(rhs.get());
811 template <class U = T, detail::enable_if_t<std::is_nothrow_move_constructible<U>::value> * =
nullptr>
814 if (!this->m_has_val && rhs.m_has_val) {
815 geterr().~unexpected<E>();
816 construct(std::move(rhs).get());
818 assign_common(std::move(rhs));
822 template <class U = T, detail::enable_if_t<!std::is_nothrow_move_constructible<U>::value> * =
nullptr>
825 if (!this->m_has_val && rhs.m_has_val) {
826 auto tmp = std::move(geterr());
827 geterr().~unexpected<E>();
828#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
830 construct(std::move(rhs).get());
832 geterr() = std::move(tmp);
836 construct(std::move(rhs).get());
839 assign_common(std::move(rhs));
848 if (!this->m_has_val && rhs.m_has_val) {
849 geterr().~unexpected<E>();
850 construct(rhs.get());
858 if (!this->m_has_val && rhs.m_has_val) {
859 geterr().~unexpected<E>();
860 construct(std::move(rhs).get());
862 assign_common(std::move(rhs));
870 void assign_common(Rhs &&rhs)
872 if (this->m_has_val) {
874 get() = std::forward<Rhs>(rhs).get();
877 construct_error(std::forward<Rhs>(rhs).geterr());
880 if (!rhs.m_has_val) {
881 geterr() = std::forward<Rhs>(rhs).geterr();
886 bool has_value()
const
888 return this->m_has_val;
891 TL_EXPECTED_11_CONSTEXPR T &get() &
895 constexpr const T &get()
const &
899 TL_EXPECTED_11_CONSTEXPR T &&get() &&
901 return std::move(this->m_val);
903#ifndef TL_EXPECTED_NO_CONSTRR
904 constexpr const T &&get()
const &&
906 return std::move(this->m_val);
912 return this->m_unexpect;
916 return this->m_unexpect;
920 return std::move(this->m_unexpect);
922#ifndef TL_EXPECTED_NO_CONSTRR
925 return std::move(this->m_unexpect);
929 TL_EXPECTED_11_CONSTEXPR
void destroy_val()
941 template <
class... Args>
942 void construct()
noexcept
944 this->m_has_val =
true;
950 void construct_with(Rhs &&)
noexcept
952 this->m_has_val =
true;
955 template <
class... Args>
956 void construct_error(Args &&...args)
noexcept
958 new (std::addressof(this->m_unexpect))
unexpected<E>(std::forward<Args>(args)...);
959 this->m_has_val =
false;
963 void assign(Rhs &&rhs)
noexcept
965 if (!this->m_has_val) {
967 geterr().~unexpected<E>();
970 geterr() = std::forward<Rhs>(rhs).geterr();
973 if (!rhs.m_has_val) {
974 construct_error(std::forward<Rhs>(rhs).geterr());
979 bool has_value()
const
981 return this->m_has_val;
986 return this->m_unexpect;
990 return this->m_unexpect;
994 return std::move(this->m_unexpect);
996#ifndef TL_EXPECTED_NO_CONSTRR
999 return std::move(this->m_unexpect);
1003 TL_EXPECTED_11_CONSTEXPR
void destroy_val()
1011template <
class T,
class E,
1012 bool = is_void_or<T, TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::value &&
1013 TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>
1019template <
class T,
class E>
1026 if (rhs.has_value()) {
1027 this->construct_with(rhs);
1029 this->construct_error(rhs.geterr());
1043#ifndef TL_EXPECTED_GCC49
1044template <
class T,
class E,
1045 bool = is_void_or<T, std::is_trivially_move_constructible<T>>::value &&
1046 std::is_trivially_move_constructible<E>::value>
1051template <
class T,
class E,
bool = false>
1054template <
class T,
class E>
1064 if (rhs.has_value()) {
1065 this->construct_with(std::move(rhs));
1067 this->construct_error(std::move(rhs.geterr()));
1075template <
class T,
class E,
1076 bool = is_void_or<T,
conjunction<TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T),
1077 TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T),
1078 TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value &&
1079 TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value &&
1080 TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value &&
1081 TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>
1086template <
class T,
class E>
1107#ifndef TL_EXPECTED_GCC49
1108template <
class T,
class E,
1109 bool = is_void_or<T, conjunction<std::is_trivially_destructible<T>, std::is_trivially_move_constructible<T>,
1110 std::is_trivially_move_assignable<T>>>::value &&
1111 std::is_trivially_destructible<E>::value && std::is_trivially_move_constructible<E>::value &&
1112 std::is_trivially_move_assignable<E>::value>
1117template <
class T,
class E,
bool = false>
1121template <
class T,
class E>
1133 std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value)
1135 this->assign(std::move(rhs));
1142template <
class T,
class E,
1143 bool EnableCopy = (is_copy_constructible_or_void<T>::value && std::is_copy_constructible<E>::value),
1144 bool EnableMove = (is_move_constructible_or_void<T>::value && std::is_move_constructible<E>::value)>
1153template <
class T,
class E>
1162template <
class T,
class E>
1171template <
class T,
class E>
1183template <
class T,
class E,
1184 bool EnableCopy = (is_copy_constructible_or_void<T>::value && std::is_copy_constructible<E>::value &&
1185 is_copy_assignable_or_void<T>::value && std::is_copy_assignable<E>::value),
1186 bool EnableMove = (is_move_constructible_or_void<T>::value && std::is_move_constructible<E>::value &&
1187 is_move_assignable_or_void<T>::value && std::is_move_assignable<E>::value)>
1196template <
class T,
class E>
1205template <
class T,
class E>
1214template <
class T,
class E>
1232template <class T, class E, bool Enable = std::is_default_constructible<T>::value || std::is_void<T>::value>
1246template <
class T,
class E>
1267 virtual const char *what()
const noexcept override
1269 return "Bad expected access";
1272 const E &error()
const &
1280 const E &&error()
const &&
1282 return std::move(m_val);
1286 return std::move(m_val);
1300template <
class T,
class E>
1305 static_assert(!std::is_reference<T>::value,
"T must not be a reference");
1306 static_assert(!std::is_same<T, std::remove_cv<in_place_t>::type>::value,
"T must not be in_place_t");
1307 static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,
"T must not be unexpect_t");
1308 static_assert(!std::is_same<T, typename std::remove_cv<unexpected<E>>::type>::value,
"T must not be unexpected<E>");
1309 static_assert(!std::is_reference<E>::value,
"E must not be a reference");
1313 return std::addressof(this->m_val);
1315 const T *valptr()
const
1317 return std::addressof(this->m_val);
1321 return std::addressof(this->m_unexpect);
1325 return std::addressof(this->m_unexpect);
1328 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1329 TL_EXPECTED_11_CONSTEXPR U &val()
1335 return this->m_unexpect;
1338 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1339 constexpr const U &val()
const
1345 return this->m_unexpect;
1352 typedef T value_type;
1353 typedef E error_type;
1356#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
1357 !defined(TL_EXPECTED_GCC55)
1359 TL_EXPECTED_11_CONSTEXPR
auto and_then(F &&f) &
1361 return and_then_impl(*
this, std::forward<F>(f));
1364 TL_EXPECTED_11_CONSTEXPR
auto and_then(F &&f) &&
1366 return and_then_impl(std::move(*
this), std::forward<F>(f));
1369 constexpr auto and_then(F &&f)
const &
1371 return and_then_impl(*
this, std::forward<F>(f));
1374#ifndef TL_EXPECTED_NO_CONSTRR
1376 constexpr auto and_then(F &&f)
const &&
1378 return and_then_impl(std::move(*
this), std::forward<F>(f));
1384 TL_EXPECTED_11_CONSTEXPR
auto and_then(F &&f) & ->
decltype(and_then_impl(std::declval<expected &>(),
1385 std::forward<F>(f)))
1387 return and_then_impl(*
this, std::forward<F>(f));
1390 TL_EXPECTED_11_CONSTEXPR
auto and_then(F &&f) && ->
decltype(and_then_impl(std::declval<expected &&>(),
1391 std::forward<F>(f)))
1393 return and_then_impl(std::move(*
this), std::forward<F>(f));
1396 constexpr auto and_then(F &&f)
const & ->
decltype(and_then_impl(std::declval<expected const &>(),
1397 std::forward<F>(f)))
1399 return and_then_impl(*
this, std::forward<F>(f));
1402#ifndef TL_EXPECTED_NO_CONSTRR
1404 constexpr auto and_then(F &&f)
const && ->
decltype(and_then_impl(std::declval<expected const &&>(),
1405 std::forward<F>(f)))
1407 return and_then_impl(std::move(*
this), std::forward<F>(f));
1412#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
1413 !defined(TL_EXPECTED_GCC55)
1415 TL_EXPECTED_11_CONSTEXPR
auto map(F &&f) &
1417 return expected_map_impl(*
this, std::forward<F>(f));
1420 TL_EXPECTED_11_CONSTEXPR
auto map(F &&f) &&
1422 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1425 constexpr auto map(F &&f)
const &
1427 return expected_map_impl(*
this, std::forward<F>(f));
1430 constexpr auto map(F &&f)
const &&
1432 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1436 TL_EXPECTED_11_CONSTEXPR
decltype(expected_map_impl(std::declval<expected &>(), std::declval<F &&>())) map(F &&f) &
1438 return expected_map_impl(*
this, std::forward<F>(f));
1441 TL_EXPECTED_11_CONSTEXPR
decltype(expected_map_impl(std::declval<expected>(), std::declval<F &&>())) map(F &&f) &&
1443 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1446 constexpr decltype(expected_map_impl(std::declval<const expected &>(), std::declval<F &&>())) map(F &&f)
const &
1448 return expected_map_impl(*
this, std::forward<F>(f));
1451#ifndef TL_EXPECTED_NO_CONSTRR
1453 constexpr decltype(expected_map_impl(std::declval<const expected &&>(), std::declval<F &&>())) map(F &&f)
const &&
1455 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1460#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
1461 !defined(TL_EXPECTED_GCC55)
1463 TL_EXPECTED_11_CONSTEXPR
auto transform(F &&f) &
1465 return expected_map_impl(*
this, std::forward<F>(f));
1468 TL_EXPECTED_11_CONSTEXPR
auto transform(F &&f) &&
1470 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1473 constexpr auto transform(F &&f)
const &
1475 return expected_map_impl(*
this, std::forward<F>(f));
1478 constexpr auto transform(F &&f)
const &&
1480 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1484 TL_EXPECTED_11_CONSTEXPR
decltype(expected_map_impl(std::declval<expected &>(), std::declval<F &&>())) transform(
1487 return expected_map_impl(*
this, std::forward<F>(f));
1490 TL_EXPECTED_11_CONSTEXPR
decltype(expected_map_impl(std::declval<expected>(), std::declval<F &&>())) transform(
1493 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1496 constexpr decltype(expected_map_impl(std::declval<const expected &>(), std::declval<F &&>())) transform(
1499 return expected_map_impl(*
this, std::forward<F>(f));
1502#ifndef TL_EXPECTED_NO_CONSTRR
1504 constexpr decltype(expected_map_impl(std::declval<const expected &&>(), std::declval<F &&>())) transform(
1507 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1512#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
1513 !defined(TL_EXPECTED_GCC55)
1515 TL_EXPECTED_11_CONSTEXPR
auto map_error(F &&f) &
1517 return map_error_impl(*
this, std::forward<F>(f));
1520 TL_EXPECTED_11_CONSTEXPR
auto map_error(F &&f) &&
1522 return map_error_impl(std::move(*
this), std::forward<F>(f));
1525 constexpr auto map_error(F &&f)
const &
1527 return map_error_impl(*
this, std::forward<F>(f));
1530 constexpr auto map_error(F &&f)
const &&
1532 return map_error_impl(std::move(*
this), std::forward<F>(f));
1536 TL_EXPECTED_11_CONSTEXPR
decltype(map_error_impl(std::declval<expected &>(), std::declval<F &&>())) map_error(
1539 return map_error_impl(*
this, std::forward<F>(f));
1542 TL_EXPECTED_11_CONSTEXPR
decltype(map_error_impl(std::declval<expected &&>(), std::declval<F &&>())) map_error(
1545 return map_error_impl(std::move(*
this), std::forward<F>(f));
1548 constexpr decltype(map_error_impl(std::declval<const expected &>(), std::declval<F &&>())) map_error(F &&f)
const &
1550 return map_error_impl(*
this, std::forward<F>(f));
1553#ifndef TL_EXPECTED_NO_CONSTRR
1555 constexpr decltype(map_error_impl(std::declval<const expected &&>(), std::declval<F &&>())) map_error(
1558 return map_error_impl(std::move(*
this), std::forward<F>(f));
1562#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
1563 !defined(TL_EXPECTED_GCC55)
1565 TL_EXPECTED_11_CONSTEXPR
auto transform_error(F &&f) &
1567 return map_error_impl(*
this, std::forward<F>(f));
1570 TL_EXPECTED_11_CONSTEXPR
auto transform_error(F &&f) &&
1572 return map_error_impl(std::move(*
this), std::forward<F>(f));
1575 constexpr auto transform_error(F &&f)
const &
1577 return map_error_impl(*
this, std::forward<F>(f));
1580 constexpr auto transform_error(F &&f)
const &&
1582 return map_error_impl(std::move(*
this), std::forward<F>(f));
1586 TL_EXPECTED_11_CONSTEXPR
decltype(map_error_impl(std::declval<expected &>(), std::declval<F &&>())) transform_error(
1589 return map_error_impl(*
this, std::forward<F>(f));
1592 TL_EXPECTED_11_CONSTEXPR
decltype(map_error_impl(std::declval<expected &&>(), std::declval<F &&>()))
1593 transform_error(F &&f) &&
1595 return map_error_impl(std::move(*
this), std::forward<F>(f));
1598 constexpr decltype(map_error_impl(std::declval<const expected &>(), std::declval<F &&>())) transform_error(
1601 return map_error_impl(*
this, std::forward<F>(f));
1604#ifndef TL_EXPECTED_NO_CONSTRR
1606 constexpr decltype(map_error_impl(std::declval<const expected &&>(), std::declval<F &&>())) transform_error(
1609 return map_error_impl(std::move(*
this), std::forward<F>(f));
1614 expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) &
1616 return or_else_impl(*
this, std::forward<F>(f));
1620 expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) &&
1622 return or_else_impl(std::move(*
this), std::forward<F>(f));
1626 expected constexpr or_else(F &&f)
const &
1628 return or_else_impl(*
this, std::forward<F>(f));
1631#ifndef TL_EXPECTED_NO_CONSTRR
1633 expected constexpr or_else(F &&f)
const &&
1635 return or_else_impl(std::move(*
this), std::forward<F>(f));
1644 template <
class... Args, detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
nullptr>
1650 template <
class U,
class... Args,
1651 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1657 template <class G = E, detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
nullptr,
1658 detail::enable_if_t<!std::is_convertible<const G &, E>::value> * =
nullptr>
1664 template <class G = E, detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
nullptr,
1665 detail::enable_if_t<std::is_convertible<const G &, E>::value> * =
nullptr>
1671 template <class G = E, detail::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1672 detail::enable_if_t<!std::is_convertible<G &&, E>::value> * =
nullptr>
1673 explicit constexpr expected(
unexpected<G> &&e)
noexcept(std::is_nothrow_constructible<E, G &&>::value)
1678 template <class G = E, detail::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1679 detail::enable_if_t<std::is_convertible<G &&, E>::value> * =
nullptr>
1685 template <
class... Args, detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
nullptr>
1691 template <
class U,
class... Args,
1692 detail::enable_if_t<std::is_constructible<E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1698 template <
class U,
class G,
1699 detail::enable_if_t<!(std::is_convertible<U const &, T>::value &&
1700 std::is_convertible<G const &, E>::value)> * =
nullptr,
1701 detail::expected_enable_from_other<T, E, U, G, const U &, const G &> * =
nullptr>
1704 if (rhs.has_value()) {
1705 this->construct(*rhs);
1707 this->construct_error(rhs.error());
1711 template <
class U,
class G,
1712 detail::enable_if_t<(std::is_convertible<U const &, T>::value &&
1713 std::is_convertible<G const &, E>::value)> * =
nullptr,
1714 detail::expected_enable_from_other<T, E, U, G, const U &, const G &> * =
nullptr>
1717 if (rhs.has_value()) {
1718 this->construct(*rhs);
1720 this->construct_error(rhs.error());
1726 detail::enable_if_t<!(std::is_convertible<U &&, T>::value && std::is_convertible<G &&, E>::value)> * =
nullptr,
1727 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1730 if (rhs.has_value()) {
1731 this->construct(std::move(*rhs));
1733 this->construct_error(std::move(rhs.error()));
1739 detail::enable_if_t<(std::is_convertible<U &&, T>::value && std::is_convertible<G &&, E>::value)> * =
nullptr,
1740 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1743 if (rhs.has_value()) {
1744 this->construct(std::move(*rhs));
1746 this->construct_error(std::move(rhs.error()));
1750 template <class U = T, detail::enable_if_t<!std::is_convertible<U &&, T>::value> * =
nullptr,
1751 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1752 explicit TL_EXPECTED_MSVC2015_CONSTEXPR
expected(U &&v) :
expected(in_place, std::forward<U>(v))
1756 template <class U = T, detail::enable_if_t<std::is_convertible<U &&, T>::value> * =
nullptr,
1757 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1758 TL_EXPECTED_MSVC2015_CONSTEXPR
expected(U &&v) :
expected(in_place, std::forward<U>(v))
1763 class U = T,
class G = T, detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
nullptr,
1764 detail::enable_if_t<!std::is_void<G>::value> * =
nullptr,
1765 detail::enable_if_t<(!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1767 std::is_constructible<T, U>::value && std::is_assignable<G &, U>::value &&
1768 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1772 val() = std::forward<U>(v);
1774 err().~unexpected<E>();
1775 ::new (valptr()) T(std::forward<U>(v));
1776 this->m_has_val =
true;
1783 class U = T,
class G = T, detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =
nullptr,
1784 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr,
1785 detail::enable_if_t<(!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1787 std::is_constructible<T, U>::value && std::is_assignable<G &, U>::value &&
1788 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1792 val() = std::forward<U>(v);
1794 auto tmp = std::move(err());
1795 err().~unexpected<E>();
1797#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1799 ::new (valptr()) T(std::forward<U>(v));
1800 this->m_has_val =
true;
1802 err() = std::move(tmp);
1806 ::new (valptr()) T(std::forward<U>(v));
1807 this->m_has_val =
true;
1814 template <class G = E, detail::enable_if_t<std::is_nothrow_copy_constructible<G>::value &&
1815 std::is_assignable<G &, G>::value> * =
nullptr>
1821 this->destroy_val();
1823 this->m_has_val =
false;
1829 template <class G = E, detail::enable_if_t<std::is_nothrow_move_constructible<G>::value &&
1830 std::is_move_assignable<G>::value> * =
nullptr>
1834 err() = std::move(rhs);
1836 this->destroy_val();
1838 this->m_has_val =
false;
1844 template <
class... Args, detail::enable_if_t<std::is_nothrow_constructible<T, Args &&...>::value> * =
nullptr>
1845 void emplace(Args &&...args)
1850 err().~unexpected<E>();
1851 this->m_has_val =
true;
1853 ::new (valptr()) T(std::forward<Args>(args)...);
1856 template <
class... Args, detail::enable_if_t<!std::is_nothrow_constructible<T, Args &&...>::value> * =
nullptr>
1857 void emplace(Args &&...args)
1861 ::new (valptr()) T(std::forward<Args>(args)...);
1863 auto tmp = std::move(err());
1864 err().~unexpected<E>();
1866#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1868 ::new (valptr()) T(std::forward<Args>(args)...);
1869 this->m_has_val =
true;
1871 err() = std::move(tmp);
1875 ::new (valptr()) T(std::forward<Args>(args)...);
1876 this->m_has_val =
true;
1881 template <
class U,
class... Args,
1882 detail::enable_if_t<std::is_nothrow_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
1884 void emplace(std::initializer_list<U> il, Args &&...args)
1887 T t(il, std::forward<Args>(args)...);
1888 val() = std::move(t);
1890 err().~unexpected<E>();
1891 ::new (valptr()) T(il, std::forward<Args>(args)...);
1892 this->m_has_val =
true;
1896 template <
class U,
class... Args,
1897 detail::enable_if_t<!std::is_nothrow_constructible<T, std::initializer_list<U> &, Args &&...>::value> * =
1899 void emplace(std::initializer_list<U> il, Args &&...args)
1902 T t(il, std::forward<Args>(args)...);
1903 val() = std::move(t);
1905 auto tmp = std::move(err());
1906 err().~unexpected<E>();
1908#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1910 ::new (valptr()) T(il, std::forward<Args>(args)...);
1911 this->m_has_val =
true;
1913 err() = std::move(tmp);
1917 ::new (valptr()) T(il, std::forward<Args>(args)...);
1918 this->m_has_val =
true;
1924 using t_is_void = std::true_type;
1925 using t_is_not_void = std::false_type;
1926 using t_is_nothrow_move_constructible = std::true_type;
1927 using move_constructing_t_can_throw = std::false_type;
1928 using e_is_nothrow_move_constructible = std::true_type;
1929 using move_constructing_e_can_throw = std::false_type;
1931 void swap_where_both_have_value(
expected & , t_is_void)
noexcept
1936 void swap_where_both_have_value(
expected &rhs, t_is_not_void)
1939 swap(val(), rhs.val());
1942 void swap_where_only_one_has_value(
expected &rhs, t_is_void)
noexcept(std::is_nothrow_move_constructible<E>::value)
1945 rhs.err().~unexpected_type();
1946 std::swap(this->m_has_val, rhs.m_has_val);
1949 void swap_where_only_one_has_value(
expected &rhs, t_is_not_void)
1951 swap_where_only_one_has_value_and_t_is_not_void(rhs,
typename std::is_nothrow_move_constructible<T>::type{},
1952 typename std::is_nothrow_move_constructible<E>::type{});
1955 void swap_where_only_one_has_value_and_t_is_not_void(
expected &rhs, t_is_nothrow_move_constructible,
1956 e_is_nothrow_move_constructible)
noexcept
1958 auto temp = std::move(val());
1961 rhs.err().~unexpected_type();
1962 ::new (rhs.valptr()) T(std::move(temp));
1963 std::swap(this->m_has_val, rhs.m_has_val);
1966 void swap_where_only_one_has_value_and_t_is_not_void(
expected &rhs, t_is_nothrow_move_constructible,
1967 move_constructing_e_can_throw)
1969 auto temp = std::move(val());
1971#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1974 rhs.err().~unexpected_type();
1975 ::new (rhs.valptr()) T(std::move(temp));
1976 std::swap(this->m_has_val, rhs.m_has_val);
1978 val() = std::move(temp);
1983 rhs.err().~unexpected_type();
1984 ::new (rhs.valptr()) T(std::move(temp));
1985 std::swap(this->m_has_val, rhs.m_has_val);
1989 void swap_where_only_one_has_value_and_t_is_not_void(
expected &rhs, move_constructing_t_can_throw,
1990 e_is_nothrow_move_constructible)
1992 auto temp = std::move(rhs.err());
1993 rhs.err().~unexpected_type();
1994#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1996 ::new (rhs.valptr()) T(std::move(val()));
1999 std::swap(this->m_has_val, rhs.m_has_val);
2001 rhs.err() = std::move(temp);
2005 ::new (rhs.valptr()) T(std::move(val()));
2008 std::swap(this->m_has_val, rhs.m_has_val);
2013 template <
class OT = T,
class OE = E>
2015 (std::is_nothrow_move_constructible<OT>::value ||
2016 std::is_nothrow_move_constructible<OE>::value)>
2017 swap(
expected &rhs)
noexcept(std::is_nothrow_move_constructible<T>::value &&
2021 if (has_value() && rhs.has_value()) {
2022 swap_where_both_have_value(rhs,
typename std::is_void<T>::type{});
2023 }
else if (!has_value() && rhs.has_value()) {
2025 }
else if (has_value()) {
2026 swap_where_only_one_has_value(rhs,
typename std::is_void<T>::type{});
2029 swap(err(), rhs.err());
2033 constexpr const T *operator->()
const
2035 TL_ASSERT(has_value());
2038 TL_EXPECTED_11_CONSTEXPR T *operator->()
2040 TL_ASSERT(has_value());
2044 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2045 constexpr const U &operator*()
const &
2047 TL_ASSERT(has_value());
2050 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2051 TL_EXPECTED_11_CONSTEXPR U &operator*() &
2053 TL_ASSERT(has_value());
2056 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2057 constexpr const U &&operator*()
const &&
2059 TL_ASSERT(has_value());
2060 return std::move(val());
2062 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2063 TL_EXPECTED_11_CONSTEXPR U &&operator*() &&
2065 TL_ASSERT(has_value());
2066 return std::move(val());
2068 constexpr bool has_value()
const noexcept
2070 return this->m_has_val;
2072 constexpr bool has_error()
const noexcept
2074 return !(this->has_value());
2076 constexpr explicit operator bool()
const noexcept
2078 return this->m_has_val;
2081 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2082 TL_EXPECTED_11_CONSTEXPR
const U &value()
const &
2087 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2088 TL_EXPECTED_11_CONSTEXPR U &value() &
2093 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2094 TL_EXPECTED_11_CONSTEXPR
const U &&value()
const &&
2097 return std::move(val());
2099 template <class U = T, detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
2100 TL_EXPECTED_11_CONSTEXPR U &&value() &&
2103 return std::move(val());
2106 constexpr const E &error()
const &
2108 TL_ASSERT(!has_value());
2109 return err().value();
2111 TL_EXPECTED_11_CONSTEXPR E &error() &
2113 TL_ASSERT(!has_value());
2114 return err().value();
2116 constexpr const E &&error()
const &&
2118 TL_ASSERT(!has_value());
2119 return std::move(err().value());
2121 TL_EXPECTED_11_CONSTEXPR E &&error() &&
2123 TL_ASSERT(!has_value());
2124 return std::move(err().value());
2128 constexpr T value_or(U &&v)
const &
2130 static_assert(std::is_copy_constructible<T>::value && std::is_convertible<U &&, T>::value,
2131 "T must be copy-constructible and convertible to from U&&");
2132 return bool(*
this) ? **this :
static_cast<T
>(std::forward<U>(v));
2135 TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) &&
2137 static_assert(std::is_move_constructible<T>::value && std::is_convertible<U &&, T>::value,
2138 "T must be move-constructible and convertible to from U&&");
2139 return bool(*
this) ? std::move(**
this) :
static_cast<T
>(std::forward<U>(v));
2143 template <
class G = E>
2144 constexpr E error_or(G &&e)
const &
2146 static_assert(std::is_copy_constructible<E>::value && std::is_convertible<G, E>::value,
2147 "E must be copy-constructible and convertible to from G&&");
2148 return has_value() ? std::forward<G>(e) : error();
2150 template <
class G = E>
2151 TL_EXPECTED_11_CONSTEXPR E error_or(G &&e) &&
2153 static_assert(std::is_move_constructible<E>::value && std::is_convertible<G, E>::value,
2154 "E must be move-constructible and convertible to from G&&");
2155 return has_value() ? std::forward<G>(e) : std::move(error());
2161using exp_t =
typename detail::decay_t<Exp>::value_type;
2163using err_t =
typename detail::decay_t<Exp>::error_type;
2164template <
class Exp,
class Ret>
2167#ifdef TL_EXPECTED_CXX14
2168template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2169 class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>()))>
2170constexpr auto and_then_impl(Exp &&exp, F &&f)
2174 return exp.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
2175 : Ret(unexpect, std::forward<Exp>(exp).error());
2178template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2179 class Ret = decltype(detail::invoke(std::declval<F>()))>
2180constexpr auto and_then_impl(Exp &&exp, F &&f)
2182 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
2184 return exp.has_value() ? detail::invoke(std::forward<F>(f)) : Ret(unexpect, std::forward<Exp>(exp).error());
2189template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>())),
2190 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr>
2191auto and_then_impl(Exp &&exp, F &&f) -> Ret
2195 return exp.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
2196 : Ret(unexpect, std::forward<Exp>(exp).error());
2199template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>())),
2200 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr>
2201constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret
2205 return exp.has_value() ? detail::invoke(std::forward<F>(f)) : Ret(unexpect, std::forward<Exp>(exp).error());
2209#ifdef TL_EXPECTED_CXX14
2210template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2211 class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>())),
2212 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2213constexpr auto expected_map_impl(Exp &&exp, F &&f)
2215 using result = ret_t<Exp, detail::decay_t<Ret>>;
2216 return exp.has_value() ? result(detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp)))
2217 : result(unexpect, std::forward<Exp>(exp).error());
2220template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2221 class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>())),
2222 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2223auto expected_map_impl(Exp &&exp, F &&f)
2225 using result = expected<void, err_t<Exp>>;
2226 if (exp.has_value()) {
2227 detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2231 return result(unexpect, std::forward<Exp>(exp).error());
2234template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2235 class Ret = decltype(detail::invoke(std::declval<F>())),
2236 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2237constexpr auto expected_map_impl(Exp &&exp, F &&f)
2239 using result = ret_t<Exp, detail::decay_t<Ret>>;
2240 return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
2241 : result(unexpect, std::forward<Exp>(exp).error());
2244template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2245 class Ret = decltype(detail::invoke(std::declval<F>())),
2246 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2247auto expected_map_impl(Exp &&exp, F &&f)
2249 using result = expected<void, err_t<Exp>>;
2250 if (exp.has_value()) {
2251 detail::invoke(std::forward<F>(f));
2255 return result(unexpect, std::forward<Exp>(exp).error());
2258template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2259 class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>())),
2260 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2262constexpr auto expected_map_impl(Exp &&exp, F &&f) -> ret_t<Exp, detail::decay_t<Ret>>
2264 using result = ret_t<Exp, detail::decay_t<Ret>>;
2266 return exp.has_value() ? result(detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp)))
2267 : result(unexpect, std::forward<Exp>(exp).error());
2270template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2271 class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Exp>())),
2272 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2274auto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>>
2276 if (exp.has_value()) {
2277 detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2281 return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
2284template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2285 class Ret = decltype(detail::invoke(std::declval<F>())),
2286 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2288constexpr auto expected_map_impl(Exp &&exp, F &&f) -> ret_t<Exp, detail::decay_t<Ret>>
2290 using result = ret_t<Exp, detail::decay_t<Ret>>;
2292 return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
2293 : result(unexpect, std::forward<Exp>(exp).error());
2296template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2297 class Ret = decltype(detail::invoke(std::declval<F>())),
2298 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2300auto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>>
2302 if (exp.has_value()) {
2303 detail::invoke(std::forward<F>(f));
2307 return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
2311#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && !defined(TL_EXPECTED_GCC54) && \
2312 !defined(TL_EXPECTED_GCC55)
2313template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2314 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2315 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2316constexpr auto map_error_impl(Exp &&exp, F &&f)
2318 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2319 return exp.has_value() ? result(*std::forward<Exp>(exp))
2320 : result(unexpect, detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()));
2322template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2323 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2324 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2325auto map_error_impl(Exp &&exp, F &&f)
2327 using result = expected<exp_t<Exp>, monostate>;
2328 if (exp.has_value()) {
2329 return result(*std::forward<Exp>(exp));
2332 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2333 return result(unexpect, monostate{});
2335template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2336 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2337 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2338constexpr auto map_error_impl(Exp &&exp, F &&f)
2340 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2341 return exp.has_value() ? result()
2342 : result(unexpect, detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()));
2344template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2345 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2346 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2347auto map_error_impl(Exp &&exp, F &&f)
2349 using result = expected<exp_t<Exp>, monostate>;
2350 if (exp.has_value()) {
2354 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2355 return result(unexpect, monostate{});
2358template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2359 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2360 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2361constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, detail::decay_t<Ret>>
2363 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2365 return exp.has_value() ? result(*std::forward<Exp>(exp))
2366 : result(unexpect, detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()));
2369template <
class Exp,
class F, detail::enable_if_t<!std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2370 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2371 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2372auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate>
2374 using result = expected<exp_t<Exp>, monostate>;
2375 if (exp.has_value()) {
2376 return result(*std::forward<Exp>(exp));
2379 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2380 return result(unexpect, monostate{});
2383template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2384 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2385 detail::enable_if_t<!std::is_
void<Ret>::value> * =
nullptr>
2386constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, detail::decay_t<Ret>>
2388 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2390 return exp.has_value() ? result()
2391 : result(unexpect, detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()));
2394template <
class Exp,
class F, detail::enable_if_t<std::is_
void<exp_t<Exp>>::value> * =
nullptr,
2395 class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2396 detail::enable_if_t<std::is_
void<Ret>::value> * =
nullptr>
2397auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate>
2399 using result = expected<exp_t<Exp>, monostate>;
2400 if (exp.has_value()) {
2404 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2405 return result(unexpect, monostate{});
2409#ifdef TL_EXPECTED_CXX14
2410template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2411 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2412constexpr auto or_else_impl(Exp &&exp, F &&f)
2414 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
2415 return exp.has_value() ? std::forward<Exp>(exp)
2416 : detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2419template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2420 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2421detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f)
2423 return exp.has_value()
2424 ? std::forward<Exp>(exp)
2425 : (detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()), std::forward<Exp>(exp));
2428template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2429 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2430auto or_else_impl(Exp &&exp, F &&f) -> Ret
2432 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
2433 return exp.has_value() ? std::forward<Exp>(exp)
2434 : detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2437template <class Exp, class F, class Ret = decltype(detail::invoke(std::declval<F>(), std::declval<Exp>().error())),
2438 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2439detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f)
2441 return exp.has_value()
2442 ? std::forward<Exp>(exp)
2443 : (detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error()), std::forward<Exp>(exp));
2448template <
class T,
class E,
class U,
class F>
2449constexpr bool operator==(
const expected<T, E> &lhs,
const expected<U, F> &rhs)
2451 return (lhs.has_value() != rhs.has_value()) ? false
2452 : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
2454template <
class T,
class E,
class U,
class F>
2455constexpr bool operator!=(
const expected<T, E> &lhs,
const expected<U, F> &rhs)
2457 return (lhs.has_value() != rhs.has_value()) ? true : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);
2459template <
class E,
class F>
2460constexpr bool operator==(
const expected<void, E> &lhs,
const expected<void, F> &rhs)
2462 return (lhs.has_value() != rhs.has_value()) ? false : (!lhs.has_value() ? lhs.error() == rhs.error() :
true);
2464template <
class E,
class F>
2465constexpr bool operator!=(
const expected<void, E> &lhs,
const expected<void, F> &rhs)
2467 return (lhs.has_value() != rhs.has_value()) ? true : (!lhs.has_value() ? lhs.error() == rhs.error() :
false);
2470template <
class T,
class E,
class U>
2471constexpr bool operator==(
const expected<T, E> &x,
const U &v)
2473 return x.has_value() ? *x == v :
false;
2475template <
class T,
class E,
class U>
2476constexpr bool operator==(
const U &v,
const expected<T, E> &x)
2478 return x.has_value() ? *x == v :
false;
2480template <
class T,
class E,
class U>
2481constexpr bool operator!=(
const expected<T, E> &x,
const U &v)
2483 return x.has_value() ? *x != v :
true;
2485template <
class T,
class E,
class U>
2486constexpr bool operator!=(
const U &v,
const expected<T, E> &x)
2488 return x.has_value() ? *x != v :
true;
2491template <
class T,
class E>
2492constexpr bool operator==(
const expected<T, E> &x,
const unexpected<E> &e)
2494 return x.has_value() ? false : x.error() == e.value();
2496template <
class T,
class E>
2497constexpr bool operator==(
const unexpected<E> &e,
const expected<T, E> &x)
2499 return x.has_value() ? false : x.error() == e.value();
2501template <
class T,
class E>
2502constexpr bool operator!=(
const expected<T, E> &x,
const unexpected<E> &e)
2504 return x.has_value() ? true : x.error() != e.value();
2506template <
class T,
class E>
2507constexpr bool operator!=(
const unexpected<E> &e,
const expected<T, E> &x)
2509 return x.has_value() ? true : x.error() != e.value();
2512template <
class T,
class E,
2513 detail::enable_if_t<(std::is_void<T>::value || std::is_move_constructible<T>::value) &&
2514 detail::is_swappable<T>::value && std::is_move_constructible<E>::value &&
2515 detail::is_swappable<E>::value> * =
nullptr>
2516void swap(expected<T, E> &lhs, expected<T, E> &rhs)
noexcept(
noexcept(lhs.swap(rhs)))
Definition expected.hpp:1261
Definition expected.hpp:1304
Definition expected.hpp:135
Top level namespace of M5.
Definition base64.cpp:39
STL compatibility functions and classes.
Definition expected.hpp:2188
Definition optional.hpp:132
Definition expected.hpp:1225
Definition expected.hpp:1082
Definition expected.hpp:1014
Definition expected.hpp:1233
Definition expected.hpp:1188
Definition expected.hpp:1145
Definition expected.hpp:1113
Definition expected.hpp:1047
Definition expected.hpp:724
Definition expected.hpp:672
Definition expected.hpp:449
Definition expected.hpp:399
Definition optional.hpp:266
Definition optional.hpp:251
Definition expected.hpp:438
A tag type to tell optional to construct its value in-place.
Definition optional.hpp:105
Definition expected.hpp:222