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

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