LCOV - code coverage report
Current view: top level - gcc/rust/util - expected.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 90.9 % 186 169
Test Date: 2026-02-28 14:20:25 Functions: 63.5 % 178 113
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.