LCOV - code coverage report
Current view: top level - gcc/rust/util - expected.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.8 % 49 44
Test Date: 2024-04-27 14:03:13 Functions: 66.7 % 3 2
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

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

Generated by: LCOV version 2.1-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.