LCOV - code coverage report
Current view: top level - gcc/rust/util - optional.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 80.7 % 145 117
Test Date: 2024-04-27 14:03:13 Functions: 50.0 % 66 33
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                 :             : ///
       4                 :             : // optional - An implementation of std::optional with extensions
       5                 :             : // Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama)
       6                 :             : //
       7                 :             : // Documentation available at https://tl.tartanllama.xyz/
       8                 :             : //
       9                 :             : // To the extent possible under law, the author(s) have dedicated all
      10                 :             : // copyright and related and neighboring rights to this software to the
      11                 :             : // public domain worldwide. This software is distributed without any warranty.
      12                 :             : //
      13                 :             : // You should have received a copy of the CC0 Public Domain Dedication
      14                 :             : // along with this software. If not, see
      15                 :             : // <http://creativecommons.org/publicdomain/zero/1.0/>.
      16                 :             : ///
      17                 :             : 
      18                 :             : #ifndef TL_OPTIONAL_HPP
      19                 :             : #define TL_OPTIONAL_HPP
      20                 :             : 
      21                 :             : #define TL_OPTIONAL_VERSION_MAJOR 1
      22                 :             : #define TL_OPTIONAL_VERSION_MINOR 1
      23                 :             : #define TL_OPTIONAL_VERSION_PATCH 0
      24                 :             : 
      25                 :             : #include "rust-system.h"
      26                 :             : 
      27                 :             : #if (defined(_MSC_VER) && _MSC_VER == 1900)
      28                 :             : #define TL_OPTIONAL_MSVC2015
      29                 :             : #endif
      30                 :             : 
      31                 :             : #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&              \
      32                 :             :      !defined(__clang__))
      33                 :             : #define TL_OPTIONAL_GCC49
      34                 :             : #endif
      35                 :             : 
      36                 :             : #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 &&              \
      37                 :             :      !defined(__clang__))
      38                 :             : #define TL_OPTIONAL_GCC54
      39                 :             : #endif
      40                 :             : 
      41                 :             : #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 &&              \
      42                 :             :      !defined(__clang__))
      43                 :             : #define TL_OPTIONAL_GCC55
      44                 :             : #endif
      45                 :             : 
      46                 :             : #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&              \
      47                 :             :      !defined(__clang__))
      48                 :             : // GCC < 5 doesn't support overloading on const&& for member functions
      49                 :             : #define TL_OPTIONAL_NO_CONSTRR
      50                 :             : 
      51                 :             : // GCC < 5 doesn't support some standard C++11 type traits
      52                 :             : #define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                                     \
      53                 :             :   std::has_trivial_copy_constructor<T>::value
      54                 :             : #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value
      55                 :             : 
      56                 :             : // This one will be different for GCC 5.7 if it's ever supported
      57                 :             : #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
      58                 :             : 
      59                 :             : // GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector
      60                 :             : // for non-copyable types
      61                 :             : #elif (defined(__GNUC__) && __GNUC__ < 8 &&                                                \
      62                 :             :      !defined(__clang__))
      63                 :             : #ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
      64                 :             : #define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
      65                 :             : namespace tl {
      66                 :             :   namespace detail {
      67                 :             :       template<class T>
      68                 :             :       struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T>{};
      69                 :             : #ifdef _GLIBCXX_VECTOR
      70                 :             :       template<class T, class A>
      71                 :             :       struct is_trivially_copy_constructible<std::vector<T,A>>
      72                 :             :           : std::is_trivially_copy_constructible<T>{};
      73                 :             : #endif      
      74                 :             :   }
      75                 :             : }
      76                 :             : #endif
      77                 :             : 
      78                 :             : #define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                                     \
      79                 :             :     tl::detail::is_trivially_copy_constructible<T>::value
      80                 :             : #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T)                                        \
      81                 :             :   std::is_trivially_copy_assignable<T>::value
      82                 :             : #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
      83                 :             : #else
      84                 :             : #define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                                     \
      85                 :             :   std::is_trivially_copy_constructible<T>::value
      86                 :             : #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T)                                        \
      87                 :             :   std::is_trivially_copy_assignable<T>::value
      88                 :             : #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
      89                 :             : #endif
      90                 :             : 
      91                 :             : #if __cplusplus > 201103L
      92                 :             : #define TL_OPTIONAL_CXX14
      93                 :             : #endif
      94                 :             : 
      95                 :             : // constexpr implies const in C++11, not C++14
      96                 :             : #if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) ||                \
      97                 :             :      defined(TL_OPTIONAL_GCC49))
      98                 :             : #define TL_OPTIONAL_11_CONSTEXPR
      99                 :             : #else
     100                 :             : #define TL_OPTIONAL_11_CONSTEXPR constexpr
     101                 :             : #endif
     102                 :             : 
     103                 :             : namespace tl {
     104                 :             : #ifndef TL_MONOSTATE_INPLACE_MUTEX
     105                 :             : #define TL_MONOSTATE_INPLACE_MUTEX
     106                 :             : /// Used to represent an optional with no data; essentially a bool
     107                 :             : class monostate {};
     108                 :             : 
     109                 :             : ///  A tag type to tell optional to construct its value in-place
     110                 :             : struct in_place_t {
     111                 :             :   explicit in_place_t() = default;
     112                 :             : };
     113                 :             : /// A tag to tell optional to construct its value in-place
     114                 :             : static constexpr in_place_t in_place{};
     115                 :             : #endif
     116                 :             : 
     117                 :             : template <class T> class optional;
     118                 :             : 
     119                 :             : namespace detail {
     120                 :             : #ifndef TL_TRAITS_MUTEX
     121                 :             : #define TL_TRAITS_MUTEX
     122                 :             : // C++14-style aliases for brevity
     123                 :             : template <class T> using remove_const_t = typename std::remove_const<T>::type;
     124                 :             : template <class T>
     125                 :             : using remove_reference_t = typename std::remove_reference<T>::type;
     126                 :             : template <class T> using decay_t = typename std::decay<T>::type;
     127                 :             : template <bool E, class T = void>
     128                 :             : using enable_if_t = typename std::enable_if<E, T>::type;
     129                 :             : template <bool B, class T, class F>
     130                 :             : using conditional_t = typename std::conditional<B, T, F>::type;
     131                 :             : 
     132                 :             : // std::conjunction from C++17
     133                 :             : template <class...> struct conjunction : std::true_type {};
     134                 :             : template <class B> struct conjunction<B> : B {};
     135                 :             : template <class B, class... Bs>
     136                 :             : struct conjunction<B, Bs...>
     137                 :             :     : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
     138                 :             : 
     139                 :             : #if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
     140                 :             : #define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
     141                 :             : #endif
     142                 :             : 
     143                 :             : // In C++11 mode, there's an issue in libc++'s std::mem_fn
     144                 :             : // which results in a hard-error when using it in a noexcept expression
     145                 :             : // in some cases. This is a check to workaround the common failing case.
     146                 :             : #ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
     147                 :             : template <class T> struct is_pointer_to_non_const_member_func : std::false_type{};
     148                 :             : template <class T, class Ret, class... Args>
     149                 :             : struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)> : std::true_type{};
     150                 :             : template <class T, class Ret, class... Args>
     151                 :             : struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)&> : std::true_type{};
     152                 :             : template <class T, class Ret, class... Args>
     153                 :             : struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)&&> : std::true_type{};        
     154                 :             : template <class T, class Ret, class... Args>
     155                 :             : struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile> : std::true_type{};
     156                 :             : template <class T, class Ret, class... Args>
     157                 :             : struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile&> : std::true_type{};
     158                 :             : template <class T, class Ret, class... Args>
     159                 :             : struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile&&> : std::true_type{};        
     160                 :             : 
     161                 :             : template <class T> struct is_const_or_const_ref : std::false_type{};
     162                 :             : template <class T> struct is_const_or_const_ref<T const&> : std::true_type{};
     163                 :             : template <class T> struct is_const_or_const_ref<T const> : std::true_type{};    
     164                 :             : #endif
     165                 :             : 
     166                 :             : // std::invoke from C++17
     167                 :             : // https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
     168                 :             : template <typename Fn, typename... Args,
     169                 :             : #ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
     170                 :             :           typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value 
     171                 :             :                                  && is_const_or_const_ref<Args...>::value)>, 
     172                 :             : #endif
     173                 :             :           typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,
     174                 :             :           int = 0>
     175                 :           0 : constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
     176                 :             :     noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
     177                 :             :     -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
     178                 :           0 :   return std::mem_fn(f)(std::forward<Args>(args)...);
     179                 :             : }
     180                 :             : 
     181                 :             : template <typename Fn, typename... Args,
     182                 :             :           typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
     183                 :          39 : constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
     184                 :             :     noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
     185                 :             :     -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
     186                 :          39 :   return std::forward<Fn>(f)(std::forward<Args>(args)...);
     187                 :             : }
     188                 :             : 
     189                 :             : // std::invoke_result from C++17
     190                 :             : template <class F, class, class... Us> struct invoke_result_impl;
     191                 :             : 
     192                 :             : template <class F, class... Us>
     193                 :             : struct invoke_result_impl<
     194                 :             :     F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()),
     195                 :             :     Us...> {
     196                 :             :   using type = decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
     197                 :             : };
     198                 :             : 
     199                 :             : template <class F, class... Us>
     200                 :             : using invoke_result = invoke_result_impl<F, void, Us...>;
     201                 :             : 
     202                 :             : template <class F, class... Us>
     203                 :             : using invoke_result_t = typename invoke_result<F, Us...>::type;
     204                 :             : 
     205                 :             : #if defined(_MSC_VER) && _MSC_VER <= 1900
     206                 :             : // TODO make a version which works with MSVC 2015
     207                 :             : template <class T, class U = T> struct is_swappable : std::true_type {};
     208                 :             : 
     209                 :             : template <class T, class U = T> struct is_nothrow_swappable : std::true_type {};
     210                 :             : #else
     211                 :             : // https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
     212                 :             : namespace swap_adl_tests {
     213                 :             : // if swap ADL finds this then it would call std::swap otherwise (same
     214                 :             : // signature)
     215                 :             : struct tag {};
     216                 :             : 
     217                 :             : template <class T> tag swap(T &, T &);
     218                 :             : template <class T, std::size_t N> tag swap(T (&a)[N], T (&b)[N]);
     219                 :             : 
     220                 :             : // helper functions to test if an unqualified swap is possible, and if it
     221                 :             : // becomes std::swap
     222                 :             : template <class, class> std::false_type can_swap(...) noexcept(false);
     223                 :             : template <class T, class U,
     224                 :             :           class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>
     225                 :             : std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T &>(),
     226                 :             :                                                     std::declval<U &>())));
     227                 :             : 
     228                 :             : template <class, class> std::false_type uses_std(...);
     229                 :             : template <class T, class U>
     230                 :             : std::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag>
     231                 :             : uses_std(int);
     232                 :             : 
     233                 :             : template <class T>
     234                 :             : struct is_std_swap_noexcept
     235                 :             :     : std::integral_constant<bool,
     236                 :             :                              std::is_nothrow_move_constructible<T>::value &&
     237                 :             :                                  std::is_nothrow_move_assignable<T>::value> {};
     238                 :             : 
     239                 :             : template <class T, std::size_t N>
     240                 :             : struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
     241                 :             : 
     242                 :             : template <class T, class U>
     243                 :             : struct is_adl_swap_noexcept
     244                 :             :     : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
     245                 :             : } // namespace swap_adl_tests
     246                 :             : 
     247                 :             : template <class T, class U = T>
     248                 :             : struct is_swappable
     249                 :             :     : std::integral_constant<
     250                 :             :           bool,
     251                 :             :           decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
     252                 :             :               (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
     253                 :             :                (std::is_move_assignable<T>::value &&
     254                 :             :                 std::is_move_constructible<T>::value))> {};
     255                 :             : 
     256                 :             : template <class T, std::size_t N>
     257                 :             : struct is_swappable<T[N], T[N]>
     258                 :             :     : std::integral_constant<
     259                 :             :           bool,
     260                 :             :           decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
     261                 :             :               (!decltype(
     262                 :             :                    detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||
     263                 :             :                is_swappable<T, T>::value)> {};
     264                 :             : 
     265                 :             : template <class T, class U = T>
     266                 :             : struct is_nothrow_swappable
     267                 :             :     : std::integral_constant<
     268                 :             :           bool,
     269                 :             :           is_swappable<T, U>::value &&
     270                 :             :               ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value
     271                 :             :                     &&detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
     272                 :             :                (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
     273                 :             :                     detail::swap_adl_tests::is_adl_swap_noexcept<T,
     274                 :             :                                                                  U>::value))> {
     275                 :             : };
     276                 :             : #endif
     277                 :             : #endif
     278                 :             : 
     279                 :             : // std::void_t from C++17
     280                 :             : template <class...> struct voider { using type = void; };
     281                 :             : template <class... Ts> using void_t = typename voider<Ts...>::type;
     282                 :             : 
     283                 :             : // Trait for checking if a type is a tl::optional
     284                 :             : template <class T> struct is_optional_impl : std::false_type {};
     285                 :             : template <class T> struct is_optional_impl<optional<T>> : std::true_type {};
     286                 :             : template <class T> using is_optional = is_optional_impl<decay_t<T>>;
     287                 :             : 
     288                 :             : // Change void to tl::monostate
     289                 :             : template <class U>
     290                 :             : using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>;
     291                 :             : 
     292                 :             : template <class F, class U, class = invoke_result_t<F, U>>
     293                 :             : using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>;
     294                 :             : 
     295                 :             : // Check if invoking F for some Us returns void
     296                 :             : template <class F, class = void, class... U> struct returns_void_impl;
     297                 :             : template <class F, class... U>
     298                 :             : struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...>
     299                 :             :     : std::is_void<invoke_result_t<F, U...>> {};
     300                 :             : template <class F, class... U>
     301                 :             : using returns_void = returns_void_impl<F, void, U...>;
     302                 :             : 
     303                 :             : template <class T, class... U>
     304                 :             : using enable_if_ret_void = enable_if_t<returns_void<T &&, U...>::value>;
     305                 :             : 
     306                 :             : template <class T, class... U>
     307                 :             : using disable_if_ret_void = enable_if_t<!returns_void<T &&, U...>::value>;
     308                 :             : 
     309                 :             : template <class T, class U>
     310                 :             : using enable_forward_value =
     311                 :             :     detail::enable_if_t<std::is_constructible<T, U &&>::value &&
     312                 :             :                         !std::is_same<detail::decay_t<U>, in_place_t>::value &&
     313                 :             :                         !std::is_same<optional<T>, detail::decay_t<U>>::value>;
     314                 :             : 
     315                 :             : template <class T, class U, class Other>
     316                 :             : using enable_from_other = detail::enable_if_t<
     317                 :             :     std::is_constructible<T, Other>::value &&
     318                 :             :     !std::is_constructible<T, optional<U> &>::value &&
     319                 :             :     !std::is_constructible<T, optional<U> &&>::value &&
     320                 :             :     !std::is_constructible<T, const optional<U> &>::value &&
     321                 :             :     !std::is_constructible<T, const optional<U> &&>::value &&
     322                 :             :     !std::is_convertible<optional<U> &, T>::value &&
     323                 :             :     !std::is_convertible<optional<U> &&, T>::value &&
     324                 :             :     !std::is_convertible<const optional<U> &, T>::value &&
     325                 :             :     !std::is_convertible<const optional<U> &&, T>::value>;
     326                 :             : 
     327                 :             : template <class T, class U>
     328                 :             : using enable_assign_forward = detail::enable_if_t<
     329                 :             :     !std::is_same<optional<T>, detail::decay_t<U>>::value &&
     330                 :             :     !detail::conjunction<std::is_scalar<T>,
     331                 :             :                          std::is_same<T, detail::decay_t<U>>>::value &&
     332                 :             :     std::is_constructible<T, U>::value && std::is_assignable<T &, U>::value>;
     333                 :             : 
     334                 :             : template <class T, class U, class Other>
     335                 :             : using enable_assign_from_other = detail::enable_if_t<
     336                 :             :     std::is_constructible<T, Other>::value &&
     337                 :             :     std::is_assignable<T &, Other>::value &&
     338                 :             :     !std::is_constructible<T, optional<U> &>::value &&
     339                 :             :     !std::is_constructible<T, optional<U> &&>::value &&
     340                 :             :     !std::is_constructible<T, const optional<U> &>::value &&
     341                 :             :     !std::is_constructible<T, const optional<U> &&>::value &&
     342                 :             :     !std::is_convertible<optional<U> &, T>::value &&
     343                 :             :     !std::is_convertible<optional<U> &&, T>::value &&
     344                 :             :     !std::is_convertible<const optional<U> &, T>::value &&
     345                 :             :     !std::is_convertible<const optional<U> &&, T>::value &&
     346                 :             :     !std::is_assignable<T &, optional<U> &>::value &&
     347                 :             :     !std::is_assignable<T &, optional<U> &&>::value &&
     348                 :             :     !std::is_assignable<T &, const optional<U> &>::value &&
     349                 :             :     !std::is_assignable<T &, const optional<U> &&>::value>;
     350                 :             : 
     351                 :             : // The storage base manages the actual storage, and correctly propagates
     352                 :             : // trivial destruction from T. This case is for when T is not trivially
     353                 :             : // destructible.
     354                 :             : template <class T, bool = ::std::is_trivially_destructible<T>::value>
     355                 :             : struct optional_storage_base {
     356                 :       83146 :   TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
     357                 :       73406 :       : m_dummy(), m_has_value(false) {}
     358                 :             : 
     359                 :             :   template <class... U>
     360                 :      364013 :   TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
     361                 :      566844 :       : m_value(std::forward<U>(u)...), m_has_value(true) {}
     362                 :             : 
     363                 :      427738 :   ~optional_storage_base() {
     364                 :      422988 :     if (m_has_value) {
     365                 :      423842 :       m_value.~T();
     366                 :             :       m_has_value = false;
     367                 :             :     }
     368                 :         217 :   }
     369                 :             : 
     370                 :             :   struct dummy {};
     371                 :             :   union {
     372                 :             :     dummy m_dummy;
     373                 :             :     T m_value;
     374                 :             :   };
     375                 :             : 
     376                 :             :   bool m_has_value;
     377                 :             : };
     378                 :             : 
     379                 :             : // This case is for when T is trivially destructible.
     380                 :             : template <class T> struct optional_storage_base<T, true> {
     381                 :        5873 :   TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
     382                 :        5771 :       : m_dummy(), m_has_value(false) {}
     383                 :             : 
     384                 :             :   template <class... U>
     385                 :       14197 :   TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
     386                 :        7564 :       : m_value(std::forward<U>(u)...), m_has_value(true) {}
     387                 :             : 
     388                 :             :   // No destructor, so this class is trivially destructible
     389                 :             : 
     390                 :             :   struct dummy {};
     391                 :             :   union {
     392                 :             :     dummy m_dummy;
     393                 :             :     T m_value;
     394                 :             :   };
     395                 :             : 
     396                 :             :   bool m_has_value = false;
     397                 :             : };
     398                 :             : 
     399                 :             : // This base class provides some handy member functions which can be used in
     400                 :             : // further derived classes
     401                 :      943478 : template <class T> struct optional_operations_base : optional_storage_base<T> {
     402                 :      581103 :   using optional_storage_base<T>::optional_storage_base;
     403                 :             : 
     404                 :             :   void hard_reset() noexcept {
     405                 :             :     get().~T();
     406                 :             :     this->m_has_value = false;
     407                 :             :   }
     408                 :             : 
     409                 :       77204 :   template <class... Args> void construct(Args &&... args) {
     410                 :       78225 :     new (std::addressof(this->m_value)) T(std::forward<Args>(args)...);
     411                 :       77204 :     this->m_has_value = true;
     412                 :       76291 :   }
     413                 :             : 
     414                 :             :   template <class Opt> void assign(Opt &&rhs) {
     415                 :             :     if (this->has_value()) {
     416                 :             :       if (rhs.has_value()) {
     417                 :             :         this->m_value = std::forward<Opt>(rhs).get();
     418                 :             :       } else {
     419                 :             :         this->m_value.~T();
     420                 :             :         this->m_has_value = false;
     421                 :             :       }
     422                 :             :     }
     423                 :             : 
     424                 :             :     else if (rhs.has_value()) {
     425                 :             :       construct(std::forward<Opt>(rhs).get());
     426                 :             :     }
     427                 :             :   }
     428                 :             : 
     429                 :       65013 :   bool has_value() const { return this->m_has_value; }
     430                 :             : 
     431                 :       58568 :   TL_OPTIONAL_11_CONSTEXPR T &get() & { return this->m_value; }
     432                 :        1748 :   TL_OPTIONAL_11_CONSTEXPR const T &get() const & { return this->m_value; }
     433                 :             :   TL_OPTIONAL_11_CONSTEXPR T &&get() && { return std::move(this->m_value); }
     434                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
     435                 :             :   constexpr const T &&get() const && { return std::move(this->m_value); }
     436                 :             : #endif
     437                 :             : };
     438                 :             : 
     439                 :             : // This class manages conditionally having a trivial copy constructor
     440                 :             : // This specialization is for when T is trivially copy constructible
     441                 :             : template <class T, bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>
     442                 :        5847 : struct optional_copy_base : optional_operations_base<T> {
     443                 :        8007 :   using optional_operations_base<T>::optional_operations_base;
     444                 :             : };
     445                 :             : 
     446                 :             : // This specialization is for when T is not trivially copy constructible
     447                 :             : template <class T>
     448                 :      854676 : struct optional_copy_base<T, false> : optional_operations_base<T> {
     449                 :      573096 :   using optional_operations_base<T>::optional_operations_base;
     450                 :             : 
     451                 :       79128 :   optional_copy_base() = default;
     452                 :        4044 :   optional_copy_base(const optional_copy_base &rhs)
     453                 :        4044 :   : optional_operations_base<T>() {
     454                 :        4044 :     if (rhs.has_value()) {
     455                 :        1748 :       this->construct(rhs.get());
     456                 :             :     } else {
     457                 :             :       this->m_has_value = false;
     458                 :             :     }
     459                 :        4044 :   }
     460                 :             : 
     461                 :             :   optional_copy_base(optional_copy_base &&rhs) = default;
     462                 :             :   optional_copy_base &operator=(const optional_copy_base &rhs) = default;
     463                 :             :   optional_copy_base &operator=(optional_copy_base &&rhs) = default;
     464                 :             : };
     465                 :             : 
     466                 :             : // This class manages conditionally having a trivial move constructor
     467                 :             : // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
     468                 :             : // doesn't implement an analogue to std::is_trivially_move_constructible. We
     469                 :             : // have to make do with a non-trivial move constructor even if T is trivially
     470                 :             : // move constructible
     471                 :             : #ifndef TL_OPTIONAL_GCC49
     472                 :             : template <class T, bool = std::is_trivially_move_constructible<T>::value>
     473                 :        5847 : struct optional_move_base : optional_copy_base<T> {
     474                 :        8007 :   using optional_copy_base<T>::optional_copy_base;
     475                 :             : };
     476                 :             : #else
     477                 :             : template <class T, bool = false> struct optional_move_base;
     478                 :             : #endif
     479                 :      854676 : template <class T> struct optional_move_base<T, false> : optional_copy_base<T> {
     480                 :      573096 :   using optional_copy_base<T>::optional_copy_base;
     481                 :             : 
     482                 :       18159 :   optional_move_base() = default;
     483                 :        1812 :   optional_move_base(const optional_move_base &rhs) = default;
     484                 :             : 
     485                 :       60969 :   optional_move_base(optional_move_base &&rhs) noexcept(
     486                 :       60969 :       std::is_nothrow_move_constructible<T>::value) {
     487                 :       60969 :     if (rhs.has_value()) {
     488                 :       58568 :       this->construct(std::move(rhs.get()));
     489                 :             :     } else {
     490                 :        1780 :       this->m_has_value = false;
     491                 :             :     }
     492                 :       41465 :   }
     493                 :             :   optional_move_base &operator=(const optional_move_base &rhs) = default;
     494                 :             :   optional_move_base &operator=(optional_move_base &&rhs) = default;
     495                 :             : };
     496                 :             : 
     497                 :             : // This class manages conditionally having a trivial copy assignment operator
     498                 :             : template <class T, bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) &&
     499                 :             :                           TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) &&
     500                 :             :                           TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)>
     501                 :        5847 : struct optional_copy_assign_base : optional_move_base<T> {
     502                 :        8007 :   using optional_move_base<T>::optional_move_base;
     503                 :             : };
     504                 :             : 
     505                 :             : template <class T>
     506                 :      854676 : struct optional_copy_assign_base<T, false> : optional_move_base<T> {
     507                 :      573096 :   using optional_move_base<T>::optional_move_base;
     508                 :             : 
     509                 :       18159 :   optional_copy_assign_base() = default;
     510                 :        7344 :   optional_copy_assign_base(const optional_copy_assign_base &rhs) = default;
     511                 :             : 
     512                 :       80473 :   optional_copy_assign_base(optional_copy_assign_base &&rhs) = default;
     513                 :             :   optional_copy_assign_base &operator=(const optional_copy_assign_base &rhs) {
     514                 :             :     this->assign(rhs);
     515                 :             :     return *this;
     516                 :             :   }
     517                 :             :   optional_copy_assign_base &
     518                 :             :   operator=(optional_copy_assign_base &&rhs) = default;
     519                 :             : };
     520                 :             : 
     521                 :             : // This class manages conditionally having a trivial move assignment operator
     522                 :             : // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
     523                 :             : // doesn't implement an analogue to std::is_trivially_move_assignable. We have
     524                 :             : // to make do with a non-trivial move assignment operator even if T is trivially
     525                 :             : // move assignable
     526                 :             : #ifndef TL_OPTIONAL_GCC49
     527                 :             : template <class T, bool = std::is_trivially_destructible<T>::value
     528                 :             :                        &&std::is_trivially_move_constructible<T>::value
     529                 :             :                            &&std::is_trivially_move_assignable<T>::value>
     530                 :        5847 : struct optional_move_assign_base : optional_copy_assign_base<T> {
     531                 :        8007 :   using optional_copy_assign_base<T>::optional_copy_assign_base;
     532                 :             : };
     533                 :             : #else
     534                 :             : template <class T, bool = false> struct optional_move_assign_base;
     535                 :             : #endif
     536                 :             : 
     537                 :             : template <class T>
     538                 :      854676 : struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
     539                 :      573096 :   using optional_copy_assign_base<T>::optional_copy_assign_base;
     540                 :             : 
     541                 :       18159 :   optional_move_assign_base() = default;
     542                 :        7344 :   optional_move_assign_base(const optional_move_assign_base &rhs) = default;
     543                 :             : 
     544                 :      121938 :   optional_move_assign_base(optional_move_assign_base &&rhs) = default;
     545                 :             : 
     546                 :             :   optional_move_assign_base &
     547                 :             :   operator=(const optional_move_assign_base &rhs) = default;
     548                 :             : 
     549                 :             :   optional_move_assign_base &
     550                 :             :   operator=(optional_move_assign_base &&rhs) noexcept(
     551                 :             :       std::is_nothrow_move_constructible<T>::value
     552                 :             :           &&std::is_nothrow_move_assignable<T>::value) {
     553                 :             :     this->assign(std::move(rhs));
     554                 :             :     return *this;
     555                 :             :   }
     556                 :             : };
     557                 :             : 
     558                 :             : // optional_delete_ctor_base will conditionally delete copy and move
     559                 :             : // constructors depending on whether T is copy/move constructible
     560                 :             : template <class T, bool EnableCopy = std::is_copy_constructible<T>::value,
     561                 :             :           bool EnableMove = std::is_move_constructible<T>::value>
     562                 :             : struct optional_delete_ctor_base {
     563                 :             :   optional_delete_ctor_base() = default;
     564                 :             :   optional_delete_ctor_base(const optional_delete_ctor_base &) = default;
     565                 :             :   optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;
     566                 :             :   optional_delete_ctor_base &
     567                 :             :   operator=(const optional_delete_ctor_base &) = default;
     568                 :             :   optional_delete_ctor_base &
     569                 :             :   operator=(optional_delete_ctor_base &&) noexcept = default;
     570                 :             : };
     571                 :             : 
     572                 :             : template <class T> struct optional_delete_ctor_base<T, true, false> {
     573                 :             :   optional_delete_ctor_base() = default;
     574                 :             :   optional_delete_ctor_base(const optional_delete_ctor_base &) = default;
     575                 :             :   optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;
     576                 :             :   optional_delete_ctor_base &
     577                 :             :   operator=(const optional_delete_ctor_base &) = default;
     578                 :             :   optional_delete_ctor_base &
     579                 :             :   operator=(optional_delete_ctor_base &&) noexcept = default;
     580                 :             : };
     581                 :             : 
     582                 :             : template <class T> struct optional_delete_ctor_base<T, false, true> {
     583                 :             :   optional_delete_ctor_base() = default;
     584                 :             :   optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;
     585                 :             :   optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;
     586                 :             :   optional_delete_ctor_base &
     587                 :             :   operator=(const optional_delete_ctor_base &) = default;
     588                 :             :   optional_delete_ctor_base &
     589                 :             :   operator=(optional_delete_ctor_base &&) noexcept = default;
     590                 :             : };
     591                 :             : 
     592                 :             : template <class T> struct optional_delete_ctor_base<T, false, false> {
     593                 :             :   optional_delete_ctor_base() = default;
     594                 :             :   optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;
     595                 :             :   optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;
     596                 :             :   optional_delete_ctor_base &
     597                 :             :   operator=(const optional_delete_ctor_base &) = default;
     598                 :             :   optional_delete_ctor_base &
     599                 :             :   operator=(optional_delete_ctor_base &&) noexcept = default;
     600                 :             : };
     601                 :             : 
     602                 :             : // optional_delete_assign_base will conditionally delete copy and move
     603                 :             : // constructors depending on whether T is copy/move constructible + assignable
     604                 :             : template <class T,
     605                 :             :           bool EnableCopy = (std::is_copy_constructible<T>::value &&
     606                 :             :                              std::is_copy_assignable<T>::value),
     607                 :             :           bool EnableMove = (std::is_move_constructible<T>::value &&
     608                 :             :                              std::is_move_assignable<T>::value)>
     609                 :             : struct optional_delete_assign_base {
     610                 :             :   optional_delete_assign_base() = default;
     611                 :             :   optional_delete_assign_base(const optional_delete_assign_base &) = default;
     612                 :             :   optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
     613                 :             :       default;
     614                 :             :   optional_delete_assign_base &
     615                 :             :   operator=(const optional_delete_assign_base &) = default;
     616                 :             :   optional_delete_assign_base &
     617                 :             :   operator=(optional_delete_assign_base &&) noexcept = default;
     618                 :             : };
     619                 :             : 
     620                 :             : template <class T> struct optional_delete_assign_base<T, true, false> {
     621                 :             :   optional_delete_assign_base() = default;
     622                 :             :   optional_delete_assign_base(const optional_delete_assign_base &) = default;
     623                 :             :   optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
     624                 :             :       default;
     625                 :             :   optional_delete_assign_base &
     626                 :             :   operator=(const optional_delete_assign_base &) = default;
     627                 :             :   optional_delete_assign_base &
     628                 :             :   operator=(optional_delete_assign_base &&) noexcept = delete;
     629                 :             : };
     630                 :             : 
     631                 :             : template <class T> struct optional_delete_assign_base<T, false, true> {
     632                 :             :   optional_delete_assign_base() = default;
     633                 :             :   optional_delete_assign_base(const optional_delete_assign_base &) = default;
     634                 :             :   optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
     635                 :             :       default;
     636                 :             :   optional_delete_assign_base &
     637                 :             :   operator=(const optional_delete_assign_base &) = delete;
     638                 :             :   optional_delete_assign_base &
     639                 :             :   operator=(optional_delete_assign_base &&) noexcept = default;
     640                 :             : };
     641                 :             : 
     642                 :             : template <class T> struct optional_delete_assign_base<T, false, false> {
     643                 :             :   optional_delete_assign_base() = default;
     644                 :             :   optional_delete_assign_base(const optional_delete_assign_base &) = default;
     645                 :             :   optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
     646                 :             :       default;
     647                 :             :   optional_delete_assign_base &
     648                 :             :   operator=(const optional_delete_assign_base &) = delete;
     649                 :             :   optional_delete_assign_base &
     650                 :             :   operator=(optional_delete_assign_base &&) noexcept = delete;
     651                 :             : };
     652                 :             : 
     653                 :             : } // namespace detail
     654                 :             : 
     655                 :             : /// A tag type to represent an empty optional
     656                 :             : struct nullopt_t {
     657                 :             :   struct do_not_use {};
     658                 :             :   constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept {}
     659                 :             : };
     660                 :             : /// Represents an empty optional
     661                 :             : static constexpr nullopt_t nullopt{nullopt_t::do_not_use{},
     662                 :             :                                    nullopt_t::do_not_use{}};
     663                 :             : 
     664                 :             : /// An optional object is an object that contains the storage for another
     665                 :             : /// object and manages the lifetime of this contained object, if any. The
     666                 :             : /// contained object may be initialized after the optional object has been
     667                 :             : /// initialized, and may be destroyed before the optional object has been
     668                 :             : /// destroyed. The initialization state of the contained object is tracked by
     669                 :             : /// the optional object.
     670                 :             : template <class T>
     671                 :             : class optional : private detail::optional_move_assign_base<T>,
     672                 :             :                  private detail::optional_delete_ctor_base<T>,
     673                 :             :                  private detail::optional_delete_assign_base<T> {
     674                 :             :   using base = detail::optional_move_assign_base<T>;
     675                 :             : 
     676                 :             :   static_assert(!std::is_same<T, in_place_t>::value,
     677                 :             :                 "instantiation of optional with in_place_t is ill-formed");
     678                 :             :   static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value,
     679                 :             :                 "instantiation of optional with nullopt_t is ill-formed");
     680                 :             : 
     681                 :             : public:
     682                 :             : // The different versions for C++14 and 11 are needed because deduced return
     683                 :             : // types are not SFINAE-safe. This provides better support for things like
     684                 :             : // generic lambdas. C.f.
     685                 :             : // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
     686                 :             : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
     687                 :             :     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
     688                 :             :   /// Carries out some operation which returns an optional on the stored
     689                 :             :   /// object if there is one.
     690                 :             :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {
     691                 :             :     using result = detail::invoke_result_t<F, T &>;
     692                 :             :     static_assert(detail::is_optional<result>::value,
     693                 :             :                   "F must return an optional");
     694                 :             : 
     695                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
     696                 :             :                        : result(nullopt);
     697                 :             :   }
     698                 :             : 
     699                 :          12 :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {
     700                 :             :     using result = detail::invoke_result_t<F, T &&>;
     701                 :             :     static_assert(detail::is_optional<result>::value,
     702                 :             :                   "F must return an optional");
     703                 :             : 
     704                 :          10 :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
     705                 :          14 :                        : result(nullopt);
     706                 :             :   }
     707                 :             : 
     708                 :             :   template <class F> constexpr auto and_then(F &&f) const & {
     709                 :             :     using result = detail::invoke_result_t<F, const T &>;
     710                 :             :     static_assert(detail::is_optional<result>::value,
     711                 :             :                   "F must return an optional");
     712                 :             : 
     713                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
     714                 :             :                        : result(nullopt);
     715                 :             :   }
     716                 :             : 
     717                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
     718                 :             :   template <class F> constexpr auto and_then(F &&f) const && {
     719                 :             :     using result = detail::invoke_result_t<F, const T &&>;
     720                 :             :     static_assert(detail::is_optional<result>::value,
     721                 :             :                   "F must return an optional");
     722                 :             : 
     723                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
     724                 :             :                        : result(nullopt);
     725                 :             :   }
     726                 :             : #endif
     727                 :             : #else
     728                 :             :   /// Carries out some operation which returns an optional on the stored
     729                 :             :   /// object if there is one.
     730                 :             :   template <class F>
     731                 :             :   TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {
     732                 :             :     using result = detail::invoke_result_t<F, T &>;
     733                 :             :     static_assert(detail::is_optional<result>::value,
     734                 :             :                   "F must return an optional");
     735                 :             : 
     736                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
     737                 :             :   }
     738                 :             : 
     739                 :             :   template <class F>
     740                 :             :   TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &&> and_then(F &&f) && {
     741                 :             :     using result = detail::invoke_result_t<F, T &&>;
     742                 :             :     static_assert(detail::is_optional<result>::value,
     743                 :             :                   "F must return an optional");
     744                 :             : 
     745                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
     746                 :             :                        : result(nullopt);
     747                 :             :   }
     748                 :             : 
     749                 :             :   template <class F>
     750                 :             :   constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {
     751                 :             :     using result = detail::invoke_result_t<F, const T &>;
     752                 :             :     static_assert(detail::is_optional<result>::value,
     753                 :             :                   "F must return an optional");
     754                 :             : 
     755                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
     756                 :             :                        : result(nullopt);
     757                 :             :   }
     758                 :             : 
     759                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
     760                 :             :   template <class F>
     761                 :             :   constexpr detail::invoke_result_t<F, const T &&> and_then(F &&f) const && {
     762                 :             :     using result = detail::invoke_result_t<F, const T &&>;
     763                 :             :     static_assert(detail::is_optional<result>::value,
     764                 :             :                   "F must return an optional");
     765                 :             : 
     766                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
     767                 :             :                        : result(nullopt);
     768                 :             :   }
     769                 :             : #endif
     770                 :             : #endif
     771                 :             : 
     772                 :             : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
     773                 :             :     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
     774                 :             :   /// Carries out some operation on the stored object if there is one.
     775                 :           0 :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {
     776                 :           0 :     return optional_map_impl(*this, std::forward<F>(f));
     777                 :             :   }
     778                 :             : 
     779                 :           0 :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
     780                 :           0 :     return optional_map_impl(std::move(*this), std::forward<F>(f));
     781                 :             :   }
     782                 :             : 
     783                 :           0 :   template <class F> constexpr auto map(F &&f) const & {
     784                 :           0 :     return optional_map_impl(*this, std::forward<F>(f));
     785                 :             :   }
     786                 :             : 
     787                 :             :   template <class F> constexpr auto map(F &&f) const && {
     788                 :             :     return optional_map_impl(std::move(*this), std::forward<F>(f));
     789                 :             :   }
     790                 :             : #else
     791                 :             :   /// Carries out some operation on the stored object if there is one.
     792                 :             :   template <class F>
     793                 :             :   TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional &>(),
     794                 :             :                                              std::declval<F &&>()))
     795                 :             :   map(F &&f) & {
     796                 :             :     return optional_map_impl(*this, std::forward<F>(f));
     797                 :             :   }
     798                 :             : 
     799                 :             :   template <class F>
     800                 :             :   TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional &&>(),
     801                 :             :                                              std::declval<F &&>()))
     802                 :             :   map(F &&f) && {
     803                 :             :     return optional_map_impl(std::move(*this), std::forward<F>(f));
     804                 :             :   }
     805                 :             : 
     806                 :             :   template <class F>
     807                 :             :   constexpr decltype(optional_map_impl(std::declval<const optional &>(),
     808                 :             :                               std::declval<F &&>()))
     809                 :             :   map(F &&f) const & {
     810                 :             :     return optional_map_impl(*this, std::forward<F>(f));
     811                 :             :   }
     812                 :             : 
     813                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
     814                 :             :   template <class F>
     815                 :             :   constexpr decltype(optional_map_impl(std::declval<const optional &&>(),
     816                 :             :                               std::declval<F &&>()))
     817                 :             :   map(F &&f) const && {
     818                 :             :     return optional_map_impl(std::move(*this), std::forward<F>(f));
     819                 :             :   }
     820                 :             : #endif
     821                 :             : #endif
     822                 :             : 
     823                 :             : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
     824                 :             :     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
     825                 :             :   /// Carries out some operation on the stored object if there is one.
     826                 :             :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & {
     827                 :             :     return optional_map_impl(*this, std::forward<F>(f));
     828                 :             :   }
     829                 :             : 
     830                 :             :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && {
     831                 :             :     return optional_map_impl(std::move(*this), std::forward<F>(f));
     832                 :             :   }
     833                 :             : 
     834                 :             :   template <class F> constexpr auto transform(F&& f) const & {
     835                 :             :     return optional_map_impl(*this, std::forward<F>(f));
     836                 :             :   }
     837                 :             : 
     838                 :             :   template <class F> constexpr auto transform(F&& f) const && {
     839                 :             :     return optional_map_impl(std::move(*this), std::forward<F>(f));
     840                 :             :   }
     841                 :             : #else
     842                 :             :   /// Carries out some operation on the stored object if there is one.
     843                 :             :   template <class F>
     844                 :             :   TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&>(),
     845                 :             :     std::declval<F&&>()))
     846                 :             :     transform(F&& f) & {
     847                 :             :     return optional_map_impl(*this, std::forward<F>(f));
     848                 :             :   }
     849                 :             : 
     850                 :             :   template <class F>
     851                 :             :   TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&&>(),
     852                 :             :     std::declval<F&&>()))
     853                 :             :     transform(F&& f) && {
     854                 :             :     return optional_map_impl(std::move(*this), std::forward<F>(f));
     855                 :             :   }
     856                 :             : 
     857                 :             :   template <class F>
     858                 :             :   constexpr decltype(optional_map_impl(std::declval<const optional&>(),
     859                 :             :     std::declval<F&&>()))
     860                 :             :     transform(F&& f) const & {
     861                 :             :     return optional_map_impl(*this, std::forward<F>(f));
     862                 :             :   }
     863                 :             : 
     864                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
     865                 :             :   template <class F>
     866                 :             :   constexpr decltype(optional_map_impl(std::declval<const optional&&>(),
     867                 :             :     std::declval<F&&>()))
     868                 :             :     transform(F&& f) const && {
     869                 :             :     return optional_map_impl(std::move(*this), std::forward<F>(f));
     870                 :             :   }
     871                 :             : #endif
     872                 :             : #endif
     873                 :             : 
     874                 :             :   /// Calls `f` if the optional is empty
     875                 :             :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
     876                 :             :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
     877                 :             :     if (has_value())
     878                 :             :       return *this;
     879                 :             : 
     880                 :             :     std::forward<F>(f)();
     881                 :             :     return nullopt;
     882                 :             :   }
     883                 :             : 
     884                 :             :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
     885                 :             :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
     886                 :             :     return has_value() ? *this : std::forward<F>(f)();
     887                 :             :   }
     888                 :             : 
     889                 :             :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
     890                 :             :   optional<T> or_else(F &&f) && {
     891                 :             :     if (has_value())
     892                 :             :       return std::move(*this);
     893                 :             : 
     894                 :             :     std::forward<F>(f)();
     895                 :             :     return nullopt;
     896                 :             :   }
     897                 :             : 
     898                 :             :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
     899                 :             :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {
     900                 :             :     return has_value() ? std::move(*this) : std::forward<F>(f)();
     901                 :             :   }
     902                 :             : 
     903                 :             :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
     904                 :             :   optional<T> or_else(F &&f) const & {
     905                 :             :     if (has_value())
     906                 :             :       return *this;
     907                 :             : 
     908                 :             :     std::forward<F>(f)();
     909                 :             :     return nullopt;
     910                 :             :   }
     911                 :             : 
     912                 :             :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
     913                 :             :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {
     914                 :             :     return has_value() ? *this : std::forward<F>(f)();
     915                 :             :   }
     916                 :             : 
     917                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
     918                 :             :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
     919                 :             :   optional<T> or_else(F &&f) const && {
     920                 :             :     if (has_value())
     921                 :             :       return std::move(*this);
     922                 :             : 
     923                 :             :     std::forward<F>(f)();
     924                 :             :     return nullopt;
     925                 :             :   }
     926                 :             : 
     927                 :             :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
     928                 :             :   optional<T> or_else(F &&f) const && {
     929                 :             :     return has_value() ? std::move(*this) : std::forward<F>(f)();
     930                 :             :   }
     931                 :             : #endif
     932                 :             : 
     933                 :             :   /// Maps the stored value with `f` if there is one, otherwise returns `u`.
     934                 :           4 :   template <class F, class U> U map_or(F &&f, U &&u) & {
     935                 :           5 :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
     936                 :             :                        : std::forward<U>(u);
     937                 :             :   }
     938                 :             : 
     939                 :             :   template <class F, class U> U map_or(F &&f, U &&u) && {
     940                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
     941                 :             :                        : std::forward<U>(u);
     942                 :             :   }
     943                 :             : 
     944                 :          19 :   template <class F, class U> U map_or(F &&f, U &&u) const & {
     945                 :          38 :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
     946                 :             :                        : std::forward<U>(u);
     947                 :             :   }
     948                 :             : 
     949                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
     950                 :             :   template <class F, class U> U map_or(F &&f, U &&u) const && {
     951                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
     952                 :             :                        : std::forward<U>(u);
     953                 :             :   }
     954                 :             : #endif
     955                 :             : 
     956                 :             :   /// Maps the stored value with `f` if there is one, otherwise calls
     957                 :             :   /// `u` and returns the result.
     958                 :             :   template <class F, class U>
     959                 :             :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {
     960                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
     961                 :             :                        : std::forward<U>(u)();
     962                 :             :   }
     963                 :             : 
     964                 :             :   template <class F, class U>
     965                 :             :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {
     966                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
     967                 :             :                        : std::forward<U>(u)();
     968                 :             :   }
     969                 :             : 
     970                 :             :   template <class F, class U>
     971                 :             :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {
     972                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
     973                 :             :                        : std::forward<U>(u)();
     974                 :             :   }
     975                 :             : 
     976                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
     977                 :             :   template <class F, class U>
     978                 :             :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {
     979                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
     980                 :             :                        : std::forward<U>(u)();
     981                 :             :   }
     982                 :             : #endif
     983                 :             : 
     984                 :             :   /// Returns `u` if `*this` has a value, otherwise an empty optional.
     985                 :             :   template <class U>
     986                 :             :   constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {
     987                 :             :     using result = optional<detail::decay_t<U>>;
     988                 :             :     return has_value() ? result{u} : result{nullopt};
     989                 :             :   }
     990                 :             : 
     991                 :             :   /// Returns `rhs` if `*this` is empty, otherwise the current value.
     992                 :             :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {
     993                 :             :     return has_value() ? *this : rhs;
     994                 :             :   }
     995                 :             : 
     996                 :             :   constexpr optional disjunction(const optional &rhs) const & {
     997                 :             :     return has_value() ? *this : rhs;
     998                 :             :   }
     999                 :             : 
    1000                 :             :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {
    1001                 :             :     return has_value() ? std::move(*this) : rhs;
    1002                 :             :   }
    1003                 :             : 
    1004                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1005                 :             :   constexpr optional disjunction(const optional &rhs) const && {
    1006                 :             :     return has_value() ? std::move(*this) : rhs;
    1007                 :             :   }
    1008                 :             : #endif
    1009                 :             : 
    1010                 :             :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {
    1011                 :             :     return has_value() ? *this : std::move(rhs);
    1012                 :             :   }
    1013                 :             : 
    1014                 :             :   constexpr optional disjunction(optional &&rhs) const & {
    1015                 :             :     return has_value() ? *this : std::move(rhs);
    1016                 :             :   }
    1017                 :             : 
    1018                 :             :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {
    1019                 :             :     return has_value() ? std::move(*this) : std::move(rhs);
    1020                 :             :   }
    1021                 :             : 
    1022                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1023                 :             :   constexpr optional disjunction(optional &&rhs) const && {
    1024                 :             :     return has_value() ? std::move(*this) : std::move(rhs);
    1025                 :             :   }
    1026                 :             : #endif
    1027                 :             : 
    1028                 :             :   /// Takes the value out of the optional, leaving it empty
    1029                 :             :   optional take() {
    1030                 :             :     optional ret = std::move(*this);
    1031                 :             :     reset();
    1032                 :             :     return ret;
    1033                 :             :   }
    1034                 :             : 
    1035                 :             :   using value_type = T;
    1036                 :             : 
    1037                 :             :   /// Constructs an optional that does not contain a value.
    1038                 :        8205 :   constexpr optional() noexcept = default;
    1039                 :             : 
    1040                 :       12450 :   constexpr optional(nullopt_t) noexcept {}
    1041                 :             : 
    1042                 :             :   /// Copy constructor
    1043                 :             :   ///
    1044                 :             :   /// If `rhs` contains a value, the stored value is direct-initialized with
    1045                 :             :   /// it. Otherwise, the constructed optional is empty.
    1046                 :        3300 :   TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) = default;
    1047                 :             : 
    1048                 :             :   /// Move constructor
    1049                 :             :   ///
    1050                 :             :   /// If `rhs` contains a value, the stored value is direct-initialized with
    1051                 :             :   /// it. Otherwise, the constructed optional is empty.
    1052                 :       70709 :   TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;
    1053                 :             : 
    1054                 :             :   /// Constructs the stored value in-place using the given arguments.
    1055                 :             :  template <class... Args>
    1056                 :             :   constexpr explicit optional(
    1057                 :             :       detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>,
    1058                 :             :       Args &&... args)
    1059                 :             :       : base(in_place, std::forward<Args>(args)...) {}
    1060                 :             : 
    1061                 :             :   template <class U, class... Args>
    1062                 :             :   TL_OPTIONAL_11_CONSTEXPR explicit optional(
    1063                 :             :       detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &,
    1064                 :             :                                                 Args &&...>::value,
    1065                 :             :                           in_place_t>,
    1066                 :             :       std::initializer_list<U> il, Args &&... args) {
    1067                 :             :     this->construct(il, std::forward<Args>(args)...);
    1068                 :             :   }
    1069                 :             : 
    1070                 :             :   /// Constructs the stored value with `u`.
    1071                 :             :   template <
    1072                 :             :       class U = T,
    1073                 :             :       detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,
    1074                 :             :       detail::enable_forward_value<T, U> * = nullptr>
    1075                 :      378210 :   constexpr optional(U &&u) : base(in_place, std::forward<U>(u)) {}
    1076                 :             : 
    1077                 :             :   template <
    1078                 :             :       class U = T,
    1079                 :             :       detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,
    1080                 :             :       detail::enable_forward_value<T, U> * = nullptr>
    1081                 :             :   constexpr explicit optional(U &&u) : base(in_place, std::forward<U>(u)) {}
    1082                 :             : 
    1083                 :             :   /// Converting copy constructor.
    1084                 :             :   template <
    1085                 :             :       class U, detail::enable_from_other<T, U, const U &> * = nullptr,
    1086                 :             :       detail::enable_if_t<std::is_convertible<const U &, T>::value> * = nullptr>
    1087                 :             :   optional(const optional<U> &rhs) {
    1088                 :             :     if (rhs.has_value()) {
    1089                 :             :       this->construct(*rhs);
    1090                 :             :     }
    1091                 :             :   }
    1092                 :             : 
    1093                 :             :   template <class U, detail::enable_from_other<T, U, const U &> * = nullptr,
    1094                 :             :             detail::enable_if_t<!std::is_convertible<const U &, T>::value> * =
    1095                 :             :                 nullptr>
    1096                 :             :   explicit optional(const optional<U> &rhs) {
    1097                 :             :     if (rhs.has_value()) {
    1098                 :             :       this->construct(*rhs);
    1099                 :             :     }
    1100                 :             :   }
    1101                 :             : 
    1102                 :             :   /// Converting move constructor.
    1103                 :             :   template <
    1104                 :             :       class U, detail::enable_from_other<T, U, U &&> * = nullptr,
    1105                 :             :       detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr>
    1106                 :           0 :   optional(optional<U> &&rhs) {
    1107                 :           0 :     if (rhs.has_value()) {
    1108                 :           0 :       this->construct(std::move(*rhs));
    1109                 :             :     }
    1110                 :           0 :   }
    1111                 :             : 
    1112                 :             :   template <
    1113                 :             :       class U, detail::enable_from_other<T, U, U &&> * = nullptr,
    1114                 :             :       detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr>
    1115                 :             :   explicit optional(optional<U> &&rhs) {
    1116                 :             :     if (rhs.has_value()) {
    1117                 :             :       this->construct(std::move(*rhs));
    1118                 :             :     }
    1119                 :             :   }
    1120                 :             : 
    1121                 :             :   /// Destroys the stored value if there is one.
    1122                 :      757276 :   ~optional() = default;
    1123                 :             : 
    1124                 :             :   /// Assignment to empty.
    1125                 :             :   ///
    1126                 :             :   /// Destroys the current value if there is one.
    1127                 :           0 :   optional &operator=(nullopt_t) noexcept {
    1128                 :           0 :     if (has_value()) {
    1129                 :           0 :       this->m_value.~T();
    1130                 :           0 :       this->m_has_value = false;
    1131                 :             :     }
    1132                 :             : 
    1133                 :             :     return *this;
    1134                 :             :   }
    1135                 :             : 
    1136                 :             :   /// Copy assignment.
    1137                 :             :   ///
    1138                 :             :   /// Copies the value from `rhs` if there is one. Otherwise resets the stored
    1139                 :             :   /// value in `*this`.
    1140                 :             :   optional &operator=(const optional &rhs) = default;
    1141                 :             : 
    1142                 :             :   /// Move assignment.
    1143                 :             :   ///
    1144                 :             :   /// Moves the value from `rhs` if there is one. Otherwise resets the stored
    1145                 :             :   /// value in `*this`.
    1146                 :             :   optional &operator=(optional &&rhs) = default;
    1147                 :             : 
    1148                 :             :   /// Assigns the stored value from `u`, destroying the old value if there was
    1149                 :             :   /// one.
    1150                 :             :   template <class U = T, detail::enable_assign_forward<T, U> * = nullptr>
    1151                 :       16915 :   optional &operator=(U &&u) {
    1152                 :       16915 :     if (has_value()) {
    1153                 :          51 :       this->m_value = std::forward<U>(u);
    1154                 :             :     } else {
    1155                 :       16888 :       this->construct(std::forward<U>(u));
    1156                 :             :     }
    1157                 :             : 
    1158                 :       16891 :     return *this;
    1159                 :             :   }
    1160                 :             : 
    1161                 :             :   /// Converting copy assignment operator.
    1162                 :             :   ///
    1163                 :             :   /// Copies the value from `rhs` if there is one. Otherwise resets the stored
    1164                 :             :   /// value in `*this`.
    1165                 :             :   template <class U,
    1166                 :             :             detail::enable_assign_from_other<T, U, const U &> * = nullptr>
    1167                 :             :   optional &operator=(const optional<U> &rhs) {
    1168                 :             :     if (has_value()) {
    1169                 :             :       if (rhs.has_value()) {
    1170                 :             :         this->m_value = *rhs;
    1171                 :             :       } else {
    1172                 :             :         this->hard_reset();
    1173                 :             :       }
    1174                 :             :     }
    1175                 :             : 
    1176                 :             :     else if (rhs.has_value()) {
    1177                 :             :       this->construct(*rhs);
    1178                 :             :     }
    1179                 :             : 
    1180                 :             :     return *this;
    1181                 :             :   }
    1182                 :             : 
    1183                 :             :   // TODO check exception guarantee
    1184                 :             :   /// Converting move assignment operator.
    1185                 :             :   ///
    1186                 :             :   /// Moves the value from `rhs` if there is one. Otherwise resets the stored
    1187                 :             :   /// value in `*this`.
    1188                 :             :   template <class U, detail::enable_assign_from_other<T, U, U> * = nullptr>
    1189                 :             :   optional &operator=(optional<U> &&rhs) {
    1190                 :             :     if (has_value()) {
    1191                 :             :       if (rhs.has_value()) {
    1192                 :             :         this->m_value = std::move(*rhs);
    1193                 :             :       } else {
    1194                 :             :         this->hard_reset();
    1195                 :             :       }
    1196                 :             :     }
    1197                 :             : 
    1198                 :             :     else if (rhs.has_value()) {
    1199                 :             :       this->construct(std::move(*rhs));
    1200                 :             :     }
    1201                 :             : 
    1202                 :             :     return *this;
    1203                 :             :   }
    1204                 :             : 
    1205                 :             :   /// Constructs the value in-place, destroying the current one if there is
    1206                 :             :   /// one.
    1207                 :             :   template <class... Args> T &emplace(Args &&... args) {
    1208                 :             :     static_assert(std::is_constructible<T, Args &&...>::value,
    1209                 :             :                   "T must be constructible with Args");
    1210                 :             : 
    1211                 :             :     *this = nullopt;
    1212                 :             :     this->construct(std::forward<Args>(args)...);
    1213                 :             :     return value();
    1214                 :             :   }
    1215                 :             : 
    1216                 :             :   template <class U, class... Args>
    1217                 :             :   detail::enable_if_t<
    1218                 :             :       std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value,
    1219                 :             :       T &>
    1220                 :             :   emplace(std::initializer_list<U> il, Args &&... args) {
    1221                 :             :     *this = nullopt;
    1222                 :             :     this->construct(il, std::forward<Args>(args)...);
    1223                 :             :     return value();    
    1224                 :             :   }
    1225                 :             : 
    1226                 :             :   /// Swaps this optional with the other.
    1227                 :             :   ///
    1228                 :             :   /// If neither optionals have a value, nothing happens.
    1229                 :             :   /// If both have a value, the values are swapped.
    1230                 :             :   /// If one has a value, it is moved to the other and the movee is left
    1231                 :             :   /// valueless.
    1232                 :             :   void
    1233                 :             :   swap(optional &rhs) noexcept(std::is_nothrow_move_constructible<T>::value
    1234                 :             :                                    &&detail::is_nothrow_swappable<T>::value) {
    1235                 :             :     using std::swap;
    1236                 :             :     if (has_value()) {
    1237                 :             :       if (rhs.has_value()) {
    1238                 :             :         swap(**this, *rhs);
    1239                 :             :       } else {
    1240                 :             :         new (std::addressof(rhs.m_value)) T(std::move(this->m_value));
    1241                 :             :         this->m_value.T::~T();
    1242                 :             :       }
    1243                 :             :     } else if (rhs.has_value()) {
    1244                 :             :       new (std::addressof(this->m_value)) T(std::move(rhs.m_value));
    1245                 :             :       rhs.m_value.T::~T();
    1246                 :             :     }
    1247                 :             :     swap(this->m_has_value, rhs.m_has_value);
    1248                 :             :   }
    1249                 :             : 
    1250                 :             :   /// Returns a pointer to the stored value
    1251                 :             :   constexpr const T *operator->() const {
    1252                 :           0 :     return std::addressof(this->m_value);
    1253                 :             :   }
    1254                 :             : 
    1255                 :             :   TL_OPTIONAL_11_CONSTEXPR T *operator->() {
    1256                 :       17125 :     return std::addressof(this->m_value);
    1257                 :             :   }
    1258                 :             : 
    1259                 :             :   /// Returns the stored value
    1260                 :       48722 :   TL_OPTIONAL_11_CONSTEXPR T &operator*() & { return this->m_value; }
    1261                 :             : 
    1262                 :       75378 :   constexpr const T &operator*() const & { return this->m_value; }
    1263                 :             : 
    1264                 :           0 :   TL_OPTIONAL_11_CONSTEXPR T &&operator*() && {
    1265                 :           0 :     return std::move(this->m_value);
    1266                 :             :   }
    1267                 :             : 
    1268                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1269                 :             :   constexpr const T &&operator*() const && { return std::move(this->m_value); }
    1270                 :             : #endif
    1271                 :             : 
    1272                 :             :   /// Returns whether or not the optional has a value
    1273                 :      514742 :   constexpr bool has_value() const noexcept { return this->m_has_value; }
    1274                 :             : 
    1275                 :        7055 :   constexpr explicit operator bool() const noexcept {
    1276                 :        7055 :     return this->m_has_value;
    1277                 :             :   }
    1278                 :             : 
    1279                 :             :   /// Returns the contained value if there is one, otherwise throws bad_optional_access
    1280                 :      366504 :   TL_OPTIONAL_11_CONSTEXPR T &value() & {
    1281                 :      366504 :     if (has_value())
    1282                 :      366504 :       return this->m_value;
    1283                 :             : 
    1284                 :           0 :     gcc_unreachable();
    1285                 :             :   }
    1286                 :        8014 :   TL_OPTIONAL_11_CONSTEXPR const T &value() const & {
    1287                 :        8014 :     if (has_value())
    1288                 :        8014 :       return this->m_value;
    1289                 :             : 
    1290                 :           0 :     gcc_unreachable();
    1291                 :             :   }
    1292                 :          14 :   TL_OPTIONAL_11_CONSTEXPR T &&value() && {
    1293                 :          14 :     if (has_value())
    1294                 :          14 :       return std::move(this->m_value);
    1295                 :             : 
    1296                 :           0 :     gcc_unreachable();
    1297                 :             :   }
    1298                 :             : 
    1299                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1300                 :             :   TL_OPTIONAL_11_CONSTEXPR const T &&value() const && {
    1301                 :             :     if (has_value())
    1302                 :             :       return std::move(this->m_value);
    1303                 :             : 
    1304                 :             :     gcc_unreachable();
    1305                 :             :   }
    1306                 :             : #endif
    1307                 :             : 
    1308                 :             :   /// Returns the stored value if there is one, otherwise returns `u`
    1309                 :             :   template <class U> constexpr T value_or(U &&u) const & {
    1310                 :             :     static_assert(std::is_copy_constructible<T>::value &&
    1311                 :             :                       std::is_convertible<U &&, T>::value,
    1312                 :             :                   "T must be copy constructible and convertible from U");
    1313                 :             :     return has_value() ? **this : static_cast<T>(std::forward<U>(u));
    1314                 :             :   }
    1315                 :             : 
    1316                 :         217 :   template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && {
    1317                 :             :     static_assert(std::is_move_constructible<T>::value &&
    1318                 :             :                       std::is_convertible<U &&, T>::value,
    1319                 :             :                   "T must be move constructible and convertible from U");
    1320                 :         217 :     return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(u));
    1321                 :             :   }
    1322                 :             : 
    1323                 :             :   /// Destroys the stored value if one exists, making the optional empty
    1324                 :             :   void reset() noexcept {
    1325                 :             :     if (has_value()) {
    1326                 :             :       this->m_value.~T();
    1327                 :             :       this->m_has_value = false;
    1328                 :             :     }
    1329                 :             :   }
    1330                 :             : }; // namespace tl
    1331                 :             : 
    1332                 :             : /// Compares two optional objects
    1333                 :             : template <class T, class U>
    1334                 :         936 : inline constexpr bool operator==(const optional<T> &lhs,
    1335                 :             :                                  const optional<U> &rhs) {
    1336                 :         936 :   return lhs.has_value() == rhs.has_value() &&
    1337                 :         936 :          (!lhs.has_value() || *lhs == *rhs);
    1338                 :             : }
    1339                 :             : template <class T, class U>
    1340                 :             : inline constexpr bool operator!=(const optional<T> &lhs,
    1341                 :             :                                  const optional<U> &rhs) {
    1342                 :             :   return lhs.has_value() != rhs.has_value() ||
    1343                 :             :          (lhs.has_value() && *lhs != *rhs);
    1344                 :             : }
    1345                 :             : template <class T, class U>
    1346                 :             : inline constexpr bool operator<(const optional<T> &lhs,
    1347                 :             :                                 const optional<U> &rhs) {
    1348                 :             :   return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
    1349                 :             : }
    1350                 :             : template <class T, class U>
    1351                 :             : inline constexpr bool operator>(const optional<T> &lhs,
    1352                 :             :                                 const optional<U> &rhs) {
    1353                 :             :   return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
    1354                 :             : }
    1355                 :             : template <class T, class U>
    1356                 :             : inline constexpr bool operator<=(const optional<T> &lhs,
    1357                 :             :                                  const optional<U> &rhs) {
    1358                 :             :   return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
    1359                 :             : }
    1360                 :             : template <class T, class U>
    1361                 :             : inline constexpr bool operator>=(const optional<T> &lhs,
    1362                 :             :                                  const optional<U> &rhs) {
    1363                 :             :   return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
    1364                 :             : }
    1365                 :             : 
    1366                 :             : /// Compares an optional to a `nullopt`
    1367                 :             : template <class T>
    1368                 :             : inline constexpr bool operator==(const optional<T> &lhs, nullopt_t) noexcept {
    1369                 :             :   return !lhs.has_value();
    1370                 :             : }
    1371                 :             : template <class T>
    1372                 :             : inline constexpr bool operator==(nullopt_t, const optional<T> &rhs) noexcept {
    1373                 :             :   return !rhs.has_value();
    1374                 :             : }
    1375                 :             : template <class T>
    1376                 :             : inline constexpr bool operator!=(const optional<T> &lhs, nullopt_t) noexcept {
    1377                 :             :   return lhs.has_value();
    1378                 :             : }
    1379                 :             : template <class T>
    1380                 :             : inline constexpr bool operator!=(nullopt_t, const optional<T> &rhs) noexcept {
    1381                 :             :   return rhs.has_value();
    1382                 :             : }
    1383                 :             : template <class T>
    1384                 :             : inline constexpr bool operator<(const optional<T> &, nullopt_t) noexcept {
    1385                 :             :   return false;
    1386                 :             : }
    1387                 :             : template <class T>
    1388                 :             : inline constexpr bool operator<(nullopt_t, const optional<T> &rhs) noexcept {
    1389                 :             :   return rhs.has_value();
    1390                 :             : }
    1391                 :             : template <class T>
    1392                 :             : inline constexpr bool operator<=(const optional<T> &lhs, nullopt_t) noexcept {
    1393                 :             :   return !lhs.has_value();
    1394                 :             : }
    1395                 :             : template <class T>
    1396                 :             : inline constexpr bool operator<=(nullopt_t, const optional<T> &) noexcept {
    1397                 :             :   return true;
    1398                 :             : }
    1399                 :             : template <class T>
    1400                 :             : inline constexpr bool operator>(const optional<T> &lhs, nullopt_t) noexcept {
    1401                 :             :   return lhs.has_value();
    1402                 :             : }
    1403                 :             : template <class T>
    1404                 :             : inline constexpr bool operator>(nullopt_t, const optional<T> &) noexcept {
    1405                 :             :   return false;
    1406                 :             : }
    1407                 :             : template <class T>
    1408                 :             : inline constexpr bool operator>=(const optional<T> &, nullopt_t) noexcept {
    1409                 :             :   return true;
    1410                 :             : }
    1411                 :             : template <class T>
    1412                 :             : inline constexpr bool operator>=(nullopt_t, const optional<T> &rhs) noexcept {
    1413                 :             :   return !rhs.has_value();
    1414                 :             : }
    1415                 :             : 
    1416                 :             : /// Compares the optional with a value.
    1417                 :             : template <class T, class U>
    1418                 :       35910 : inline constexpr bool operator==(const optional<T> &lhs, const U &rhs) {
    1419                 :       35910 :   return lhs.has_value() ? *lhs == rhs : false;
    1420                 :             : }
    1421                 :             : template <class T, class U>
    1422                 :             : inline constexpr bool operator==(const U &lhs, const optional<T> &rhs) {
    1423                 :             :   return rhs.has_value() ? lhs == *rhs : false;
    1424                 :             : }
    1425                 :             : template <class T, class U>
    1426                 :             : inline constexpr bool operator!=(const optional<T> &lhs, const U &rhs) {
    1427                 :             :   return lhs.has_value() ? *lhs != rhs : true;
    1428                 :             : }
    1429                 :             : template <class T, class U>
    1430                 :             : inline constexpr bool operator!=(const U &lhs, const optional<T> &rhs) {
    1431                 :             :   return rhs.has_value() ? lhs != *rhs : true;
    1432                 :             : }
    1433                 :             : template <class T, class U>
    1434                 :             : inline constexpr bool operator<(const optional<T> &lhs, const U &rhs) {
    1435                 :             :   return lhs.has_value() ? *lhs < rhs : true;
    1436                 :             : }
    1437                 :             : template <class T, class U>
    1438                 :             : inline constexpr bool operator<(const U &lhs, const optional<T> &rhs) {
    1439                 :             :   return rhs.has_value() ? lhs < *rhs : false;
    1440                 :             : }
    1441                 :             : template <class T, class U>
    1442                 :             : inline constexpr bool operator<=(const optional<T> &lhs, const U &rhs) {
    1443                 :             :   return lhs.has_value() ? *lhs <= rhs : true;
    1444                 :             : }
    1445                 :             : template <class T, class U>
    1446                 :             : inline constexpr bool operator<=(const U &lhs, const optional<T> &rhs) {
    1447                 :             :   return rhs.has_value() ? lhs <= *rhs : false;
    1448                 :             : }
    1449                 :             : template <class T, class U>
    1450                 :             : inline constexpr bool operator>(const optional<T> &lhs, const U &rhs) {
    1451                 :             :   return lhs.has_value() ? *lhs > rhs : false;
    1452                 :             : }
    1453                 :             : template <class T, class U>
    1454                 :             : inline constexpr bool operator>(const U &lhs, const optional<T> &rhs) {
    1455                 :             :   return rhs.has_value() ? lhs > *rhs : true;
    1456                 :             : }
    1457                 :             : template <class T, class U>
    1458                 :             : inline constexpr bool operator>=(const optional<T> &lhs, const U &rhs) {
    1459                 :             :   return lhs.has_value() ? *lhs >= rhs : false;
    1460                 :             : }
    1461                 :             : template <class T, class U>
    1462                 :             : inline constexpr bool operator>=(const U &lhs, const optional<T> &rhs) {
    1463                 :             :   return rhs.has_value() ? lhs >= *rhs : true;
    1464                 :             : }
    1465                 :             : 
    1466                 :             : template <class T,
    1467                 :             :           detail::enable_if_t<std::is_move_constructible<T>::value> * = nullptr,
    1468                 :             :           detail::enable_if_t<detail::is_swappable<T>::value> * = nullptr>
    1469                 :             : void swap(optional<T> &lhs,
    1470                 :             :           optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
    1471                 :             :   return lhs.swap(rhs);
    1472                 :             : }
    1473                 :             : 
    1474                 :             : namespace detail {
    1475                 :             : struct i_am_secret {};
    1476                 :             : } // namespace detail
    1477                 :             : 
    1478                 :             : template <class T = detail::i_am_secret, class U,
    1479                 :             :           class Ret =
    1480                 :             :               detail::conditional_t<std::is_same<T, detail::i_am_secret>::value,
    1481                 :             :                                     detail::decay_t<U>, T>>
    1482                 :             : inline constexpr optional<Ret> make_optional(U &&v) {
    1483                 :             :   return optional<Ret>(std::forward<U>(v));
    1484                 :             : }
    1485                 :             : 
    1486                 :             : template <class T, class... Args>
    1487                 :             : inline constexpr optional<T> make_optional(Args &&... args) {
    1488                 :             :   return optional<T>(in_place, std::forward<Args>(args)...);
    1489                 :             : }
    1490                 :             : template <class T, class U, class... Args>
    1491                 :             : inline constexpr optional<T> make_optional(std::initializer_list<U> il,
    1492                 :             :                                            Args &&... args) {
    1493                 :             :   return optional<T>(in_place, il, std::forward<Args>(args)...);
    1494                 :             : }
    1495                 :             : 
    1496                 :             : #if __cplusplus >= 201703L
    1497                 :             : template <class T> optional(T)->optional<T>;
    1498                 :             : #endif
    1499                 :             : 
    1500                 :             : /// \exclude
    1501                 :             : namespace detail {
    1502                 :             : #ifdef TL_OPTIONAL_CXX14
    1503                 :             : template <class Opt, class F,
    1504                 :             :           class Ret = decltype(detail::invoke(std::declval<F>(),
    1505                 :             :                                               *std::declval<Opt>())),
    1506                 :             :           detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
    1507                 :           0 : constexpr auto optional_map_impl(Opt &&opt, F &&f) {
    1508                 :           0 :   return opt.has_value()
    1509                 :           0 :              ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
    1510                 :           0 :              : optional<Ret>(nullopt);
    1511                 :             : }
    1512                 :             : 
    1513                 :             : template <class Opt, class F,
    1514                 :             :           class Ret = decltype(detail::invoke(std::declval<F>(),
    1515                 :             :                                               *std::declval<Opt>())),
    1516                 :             :           detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
    1517                 :             : auto optional_map_impl(Opt &&opt, F &&f) {
    1518                 :             :   if (opt.has_value()) {
    1519                 :             :     detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
    1520                 :             :     return make_optional(monostate{});
    1521                 :             :   }
    1522                 :             : 
    1523                 :             :   return optional<monostate>(nullopt);
    1524                 :             : }
    1525                 :             : #else
    1526                 :             : template <class Opt, class F,
    1527                 :             :           class Ret = decltype(detail::invoke(std::declval<F>(),
    1528                 :             :                                               *std::declval<Opt>())),
    1529                 :             :           detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
    1530                 :             : 
    1531                 :             : constexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional<Ret> {
    1532                 :             :   return opt.has_value()
    1533                 :             :              ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
    1534                 :             :              : optional<Ret>(nullopt);
    1535                 :             : }
    1536                 :             : 
    1537                 :             : template <class Opt, class F,
    1538                 :             :           class Ret = decltype(detail::invoke(std::declval<F>(),
    1539                 :             :                                               *std::declval<Opt>())),
    1540                 :             :           detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
    1541                 :             : 
    1542                 :             : auto optional_map_impl(Opt &&opt, F &&f) -> optional<monostate> {
    1543                 :             :   if (opt.has_value()) {
    1544                 :             :     detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
    1545                 :             :     return monostate{};
    1546                 :             :   }
    1547                 :             : 
    1548                 :             :   return nullopt;
    1549                 :             : }
    1550                 :             : #endif
    1551                 :             : } // namespace detail
    1552                 :             : 
    1553                 :             : /// Specialization for when `T` is a reference. `optional<T&>` acts similarly
    1554                 :             : /// to a `T*`, but provides more operations and shows intent more clearly.
    1555                 :             : template <class T> class optional<T &> {
    1556                 :             : public:
    1557                 :             : // The different versions for C++14 and 11 are needed because deduced return
    1558                 :             : // types are not SFINAE-safe. This provides better support for things like
    1559                 :             : // generic lambdas. C.f.
    1560                 :             : // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
    1561                 :             : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
    1562                 :             :     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
    1563                 :             : 
    1564                 :             :   /// Carries out some operation which returns an optional on the stored
    1565                 :             :   /// object if there is one.
    1566                 :             :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {
    1567                 :             :     using result = detail::invoke_result_t<F, T &>;
    1568                 :             :     static_assert(detail::is_optional<result>::value,
    1569                 :             :                   "F must return an optional");
    1570                 :             : 
    1571                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1572                 :             :                        : result(nullopt);
    1573                 :             :   }
    1574                 :             : 
    1575                 :          12 :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {
    1576                 :             :     using result = detail::invoke_result_t<F, T &>;
    1577                 :             :     static_assert(detail::is_optional<result>::value,
    1578                 :             :                   "F must return an optional");
    1579                 :             : 
    1580                 :           9 :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1581                 :           3 :                        : result(nullopt);
    1582                 :             :   }
    1583                 :             : 
    1584                 :             :   template <class F> constexpr auto and_then(F &&f) const & {
    1585                 :             :     using result = detail::invoke_result_t<F, const T &>;
    1586                 :             :     static_assert(detail::is_optional<result>::value,
    1587                 :             :                   "F must return an optional");
    1588                 :             : 
    1589                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1590                 :             :                        : result(nullopt);
    1591                 :             :   }
    1592                 :             : 
    1593                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1594                 :             :   template <class F> constexpr auto and_then(F &&f) const && {
    1595                 :             :     using result = detail::invoke_result_t<F, const T &>;
    1596                 :             :     static_assert(detail::is_optional<result>::value,
    1597                 :             :                   "F must return an optional");
    1598                 :             : 
    1599                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1600                 :             :                        : result(nullopt);
    1601                 :             :   }
    1602                 :             : #endif
    1603                 :             : #else
    1604                 :             :   /// Carries out some operation which returns an optional on the stored
    1605                 :             :   /// object if there is one.
    1606                 :             :   template <class F>
    1607                 :             :   TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {
    1608                 :             :     using result = detail::invoke_result_t<F, T &>;
    1609                 :             :     static_assert(detail::is_optional<result>::value,
    1610                 :             :                   "F must return an optional");
    1611                 :             : 
    1612                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1613                 :             :                        : result(nullopt);
    1614                 :             :   }
    1615                 :             : 
    1616                 :             :   template <class F>
    1617                 :             :   TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) && {
    1618                 :             :     using result = detail::invoke_result_t<F, T &>;
    1619                 :             :     static_assert(detail::is_optional<result>::value,
    1620                 :             :                   "F must return an optional");
    1621                 :             : 
    1622                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1623                 :             :                        : result(nullopt);
    1624                 :             :   }
    1625                 :             : 
    1626                 :             :   template <class F>
    1627                 :             :   constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {
    1628                 :             :     using result = detail::invoke_result_t<F, const T &>;
    1629                 :             :     static_assert(detail::is_optional<result>::value,
    1630                 :             :                   "F must return an optional");
    1631                 :             : 
    1632                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1633                 :             :                        : result(nullopt);
    1634                 :             :   }
    1635                 :             : 
    1636                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1637                 :             :   template <class F>
    1638                 :             :   constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const && {
    1639                 :             :     using result = detail::invoke_result_t<F, const T &>;
    1640                 :             :     static_assert(detail::is_optional<result>::value,
    1641                 :             :                   "F must return an optional");
    1642                 :             : 
    1643                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
    1644                 :             :                        : result(nullopt);
    1645                 :             :   }
    1646                 :             : #endif
    1647                 :             : #endif
    1648                 :             : 
    1649                 :             : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
    1650                 :             :     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
    1651                 :             :   /// Carries out some operation on the stored object if there is one.
    1652                 :             :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {
    1653                 :             :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1654                 :             :   }
    1655                 :             : 
    1656                 :             :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
    1657                 :             :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1658                 :             :   }
    1659                 :             : 
    1660                 :             :   template <class F> constexpr auto map(F &&f) const & {
    1661                 :             :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1662                 :             :   }
    1663                 :             : 
    1664                 :             :   template <class F> constexpr auto map(F &&f) const && {
    1665                 :             :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1666                 :             :   }
    1667                 :             : #else
    1668                 :             :   /// Carries out some operation on the stored object if there is one.
    1669                 :             :   template <class F>
    1670                 :             :   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &>(),
    1671                 :             :                                                      std::declval<F &&>()))
    1672                 :             :   map(F &&f) & {
    1673                 :             :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1674                 :             :   }
    1675                 :             : 
    1676                 :             :   template <class F>
    1677                 :             :   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &&>(),
    1678                 :             :                                                      std::declval<F &&>()))
    1679                 :             :   map(F &&f) && {
    1680                 :             :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1681                 :             :   }
    1682                 :             : 
    1683                 :             :   template <class F>
    1684                 :             :   constexpr decltype(detail::optional_map_impl(std::declval<const optional &>(),
    1685                 :             :                                       std::declval<F &&>()))
    1686                 :             :   map(F &&f) const & {
    1687                 :             :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1688                 :             :   }
    1689                 :             : 
    1690                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1691                 :             :   template <class F>
    1692                 :             :   constexpr decltype(detail::optional_map_impl(std::declval<const optional &&>(),
    1693                 :             :                                       std::declval<F &&>()))
    1694                 :             :   map(F &&f) const && {
    1695                 :             :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1696                 :             :   }
    1697                 :             : #endif
    1698                 :             : #endif
    1699                 :             : 
    1700                 :             : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
    1701                 :             :     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
    1702                 :             :   /// Carries out some operation on the stored object if there is one.
    1703                 :             :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & {
    1704                 :             :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1705                 :             :   }
    1706                 :             : 
    1707                 :             :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && {
    1708                 :             :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1709                 :             :   }
    1710                 :             : 
    1711                 :             :   template <class F> constexpr auto transform(F&& f) const & {
    1712                 :             :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1713                 :             :   }
    1714                 :             : 
    1715                 :             :   template <class F> constexpr auto transform(F&& f) const && {
    1716                 :             :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1717                 :             :   }
    1718                 :             : #else
    1719                 :             :   /// Carries out some operation on the stored object if there is one.
    1720                 :             :   template <class F>
    1721                 :             :   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(),
    1722                 :             :     std::declval<F&&>()))
    1723                 :             :     transform(F&& f) & {
    1724                 :             :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1725                 :             :   }
    1726                 :             : 
    1727                 :             :   /// \group map
    1728                 :             :   /// \synopsis template <class F> auto transform(F &&f) &&;
    1729                 :             :   template <class F>
    1730                 :             :   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(),
    1731                 :             :     std::declval<F&&>()))
    1732                 :             :     transform(F&& f) && {
    1733                 :             :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1734                 :             :   }
    1735                 :             : 
    1736                 :             :   template <class F>
    1737                 :             :   constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(),
    1738                 :             :     std::declval<F&&>()))
    1739                 :             :     transform(F&& f) const & {
    1740                 :             :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1741                 :             :   }
    1742                 :             : 
    1743                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1744                 :             :   template <class F>
    1745                 :             :   constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(),
    1746                 :             :     std::declval<F&&>()))
    1747                 :             :     transform(F&& f) const && {
    1748                 :             :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1749                 :             :   }
    1750                 :             : #endif
    1751                 :             : #endif
    1752                 :             : 
    1753                 :             :   /// Calls `f` if the optional is empty
    1754                 :             :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
    1755                 :             :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
    1756                 :             :     if (has_value())
    1757                 :             :       return *this;
    1758                 :             : 
    1759                 :             :     std::forward<F>(f)();
    1760                 :             :     return nullopt;
    1761                 :             :   }
    1762                 :             : 
    1763                 :             :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
    1764                 :             :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
    1765                 :             :     return has_value() ? *this : std::forward<F>(f)();
    1766                 :             :   }
    1767                 :             : 
    1768                 :             :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
    1769                 :             :   optional<T> or_else(F &&f) && {
    1770                 :             :     if (has_value())
    1771                 :             :       return std::move(*this);
    1772                 :             : 
    1773                 :             :     std::forward<F>(f)();
    1774                 :             :     return nullopt;
    1775                 :             :   }
    1776                 :             : 
    1777                 :             :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
    1778                 :             :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {
    1779                 :             :     return has_value() ? std::move(*this) : std::forward<F>(f)();
    1780                 :             :   }
    1781                 :             : 
    1782                 :             :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
    1783                 :             :   optional<T> or_else(F &&f) const & {
    1784                 :             :     if (has_value())
    1785                 :             :       return *this;
    1786                 :             : 
    1787                 :             :     std::forward<F>(f)();
    1788                 :             :     return nullopt;
    1789                 :             :   }
    1790                 :             : 
    1791                 :             :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
    1792                 :             :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {
    1793                 :             :     return has_value() ? *this : std::forward<F>(f)();
    1794                 :             :   }
    1795                 :             : 
    1796                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1797                 :             :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
    1798                 :             :   optional<T> or_else(F &&f) const && {
    1799                 :             :     if (has_value())
    1800                 :             :       return std::move(*this);
    1801                 :             : 
    1802                 :             :     std::forward<F>(f)();
    1803                 :             :     return nullopt;
    1804                 :             :   }
    1805                 :             : 
    1806                 :             :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
    1807                 :             :   optional<T> or_else(F &&f) const && {
    1808                 :             :     return has_value() ? std::move(*this) : std::forward<F>(f)();
    1809                 :             :   }
    1810                 :             : #endif
    1811                 :             : 
    1812                 :             :   /// Maps the stored value with `f` if there is one, otherwise returns `u`
    1813                 :             :   template <class F, class U> U map_or(F &&f, U &&u) & {
    1814                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1815                 :             :                        : std::forward<U>(u);
    1816                 :             :   }
    1817                 :             : 
    1818                 :             :   template <class F, class U> U map_or(F &&f, U &&u) && {
    1819                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
    1820                 :             :                        : std::forward<U>(u);
    1821                 :             :   }
    1822                 :             : 
    1823                 :             :   template <class F, class U> U map_or(F &&f, U &&u) const & {
    1824                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1825                 :             :                        : std::forward<U>(u);
    1826                 :             :   }
    1827                 :             : 
    1828                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1829                 :             :   template <class F, class U> U map_or(F &&f, U &&u) const && {
    1830                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
    1831                 :             :                        : std::forward<U>(u);
    1832                 :             :   }
    1833                 :             : #endif
    1834                 :             : 
    1835                 :             :   /// Maps the stored value with `f` if there is one, otherwise calls
    1836                 :             :   /// `u` and returns the result.
    1837                 :             :   template <class F, class U>
    1838                 :             :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {
    1839                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1840                 :             :                        : std::forward<U>(u)();
    1841                 :             :   }
    1842                 :             : 
    1843                 :             :   template <class F, class U>
    1844                 :             :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {
    1845                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
    1846                 :             :                        : std::forward<U>(u)();
    1847                 :             :   }
    1848                 :             : 
    1849                 :             :   template <class F, class U>
    1850                 :             :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {
    1851                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1852                 :             :                        : std::forward<U>(u)();
    1853                 :             :   }
    1854                 :             : 
    1855                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1856                 :             :   template <class F, class U>
    1857                 :             :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {
    1858                 :             :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
    1859                 :             :                        : std::forward<U>(u)();
    1860                 :             :   }
    1861                 :             : #endif
    1862                 :             : 
    1863                 :             :   /// Returns `u` if `*this` has a value, otherwise an empty optional.
    1864                 :             :   template <class U>
    1865                 :             :   constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {
    1866                 :             :     using result = optional<detail::decay_t<U>>;
    1867                 :             :     return has_value() ? result{u} : result{nullopt};
    1868                 :             :   }
    1869                 :             : 
    1870                 :             :   /// Returns `rhs` if `*this` is empty, otherwise the current value.
    1871                 :             :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {
    1872                 :             :     return has_value() ? *this : rhs;
    1873                 :             :   }
    1874                 :             : 
    1875                 :             :   constexpr optional disjunction(const optional &rhs) const & {
    1876                 :             :     return has_value() ? *this : rhs;
    1877                 :             :   }
    1878                 :             : 
    1879                 :             :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {
    1880                 :             :     return has_value() ? std::move(*this) : rhs;
    1881                 :             :   }
    1882                 :             : 
    1883                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1884                 :             :   constexpr optional disjunction(const optional &rhs) const && {
    1885                 :             :     return has_value() ? std::move(*this) : rhs;
    1886                 :             :   }
    1887                 :             : #endif
    1888                 :             : 
    1889                 :             :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {
    1890                 :             :     return has_value() ? *this : std::move(rhs);
    1891                 :             :   }
    1892                 :             : 
    1893                 :             :   constexpr optional disjunction(optional &&rhs) const & {
    1894                 :             :     return has_value() ? *this : std::move(rhs);
    1895                 :             :   }
    1896                 :             : 
    1897                 :             :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {
    1898                 :             :     return has_value() ? std::move(*this) : std::move(rhs);
    1899                 :             :   }
    1900                 :             : 
    1901                 :             : #ifndef TL_OPTIONAL_NO_CONSTRR
    1902                 :             :   constexpr optional disjunction(optional &&rhs) const && {
    1903                 :             :     return has_value() ? std::move(*this) : std::move(rhs);
    1904                 :             :   }
    1905                 :             : #endif
    1906                 :             : 
    1907                 :             :   /// Takes the value out of the optional, leaving it empty
    1908                 :             :   optional take() {
    1909                 :             :     optional ret = std::move(*this);
    1910                 :             :     reset();
    1911                 :             :     return ret;
    1912                 :             :   }
    1913                 :             : 
    1914                 :             :   using value_type = T &;
    1915                 :             : 
    1916                 :             :   /// Constructs an optional that does not contain a value.
    1917                 :       24720 :   constexpr optional() noexcept : m_value(nullptr) {}
    1918                 :             : 
    1919                 :         126 :   constexpr optional(nullopt_t) noexcept : m_value(nullptr) {}
    1920                 :             : 
    1921                 :             :   /// Copy constructor
    1922                 :             :   ///
    1923                 :             :   /// If `rhs` contains a value, the stored value is direct-initialized with
    1924                 :             :   /// it. Otherwise, the constructed optional is empty.
    1925                 :             :   TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) noexcept = default;
    1926                 :             : 
    1927                 :             :   /// Move constructor
    1928                 :             :   ///
    1929                 :             :   /// If `rhs` contains a value, the stored value is direct-initialized with
    1930                 :             :   /// it. Otherwise, the constructed optional is empty.
    1931                 :             :   TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;
    1932                 :             : 
    1933                 :             :   /// Constructs the stored value with `u`.
    1934                 :             :   template <class U = T,
    1935                 :             :             detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
    1936                 :             :                 * = nullptr>
    1937                 :        5430 :   constexpr optional(U &&u)  noexcept : m_value(std::addressof(u)) {
    1938                 :             :     static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
    1939                 :           0 :   }
    1940                 :             : 
    1941                 :             :   template <class U>
    1942                 :             :   constexpr explicit optional(const optional<U> &rhs) noexcept : optional(*rhs) {}
    1943                 :             : 
    1944                 :             :   /// No-op
    1945                 :             :   ~optional() = default;
    1946                 :             : 
    1947                 :             :   /// Assignment to empty.
    1948                 :             :   ///
    1949                 :             :   /// Destroys the current value if there is one.
    1950                 :             :   optional &operator=(nullopt_t) noexcept {
    1951                 :             :     m_value = nullptr;
    1952                 :             :     return *this;
    1953                 :             :   }
    1954                 :             : 
    1955                 :             :   /// Copy assignment.
    1956                 :             :   ///
    1957                 :             :   /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
    1958                 :             :   /// resets the stored value in `*this`.
    1959                 :             :   optional &operator=(const optional &rhs) = default;
    1960                 :             : 
    1961                 :             :   /// Rebinds this optional to `u`.
    1962                 :             :   template <class U = T,
    1963                 :             :             detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
    1964                 :             :                 * = nullptr>
    1965                 :        2284 :   optional &operator=(U &&u) {
    1966                 :             :     static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
    1967                 :        2284 :     m_value = std::addressof(u);
    1968                 :          19 :     return *this;
    1969                 :             :   }
    1970                 :             : 
    1971                 :             :   /// Converting copy assignment operator.
    1972                 :             :   ///
    1973                 :             :   /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
    1974                 :             :   /// resets the stored value in `*this`.
    1975                 :             :   template <class U> optional &operator=(const optional<U> &rhs) noexcept {
    1976                 :             :     m_value = std::addressof(rhs.value());
    1977                 :             :     return *this;
    1978                 :             :   }
    1979                 :             : 
    1980                 :             :   /// Rebinds this optional to `u`.
    1981                 :             :   template <class U = T,
    1982                 :             :             detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
    1983                 :             :                 * = nullptr>
    1984                 :             :   optional &emplace(U &&u) noexcept {
    1985                 :             :     return *this = std::forward<U>(u);
    1986                 :             :   }
    1987                 :             : 
    1988                 :             :   void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); }
    1989                 :             : 
    1990                 :             :   /// Returns a pointer to the stored value
    1991                 :             :   constexpr const T *operator->() const noexcept { return m_value; }
    1992                 :             : 
    1993                 :        2309 :   TL_OPTIONAL_11_CONSTEXPR T *operator->() noexcept { return m_value; }
    1994                 :             : 
    1995                 :             :   /// Returns the stored value
    1996                 :           1 :   TL_OPTIONAL_11_CONSTEXPR T &operator*() noexcept { return *m_value; }
    1997                 :             : 
    1998                 :             :   constexpr const T &operator*() const noexcept { return *m_value; }
    1999                 :             : 
    2000                 :      398744 :   constexpr bool has_value() const noexcept { return m_value != nullptr; }
    2001                 :             : 
    2002                 :             :   constexpr explicit operator bool() const noexcept {
    2003                 :             :     return m_value != nullptr;
    2004                 :             :   }
    2005                 :             : 
    2006                 :             :   /// Returns the contained value if there is one, otherwise throws bad_optional_access
    2007                 :        3905 :   TL_OPTIONAL_11_CONSTEXPR T &value() {
    2008                 :        3905 :     if (has_value())
    2009                 :        3905 :       return *m_value;
    2010                 :             : 
    2011                 :           0 :     gcc_unreachable();
    2012                 :             :   }
    2013                 :             :   TL_OPTIONAL_11_CONSTEXPR const T &value() const {
    2014                 :             :     if (has_value())
    2015                 :             :       return *m_value;
    2016                 :             : 
    2017                 :             :     gcc_unreachable();
    2018                 :             :   }
    2019                 :             : 
    2020                 :             :   /// Returns the stored value if there is one, otherwise returns `u`
    2021                 :             :   template <class U> constexpr T value_or(U &&u) const & noexcept {
    2022                 :             :     static_assert(std::is_copy_constructible<T>::value &&
    2023                 :             :                       std::is_convertible<U &&, T>::value,
    2024                 :             :                   "T must be copy constructible and convertible from U");
    2025                 :             :     return has_value() ? **this : static_cast<T>(std::forward<U>(u));
    2026                 :             :   }
    2027                 :             : 
    2028                 :             :   /// \group value_or
    2029                 :             :   template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && noexcept {
    2030                 :             :     static_assert(std::is_move_constructible<T>::value &&
    2031                 :             :                       std::is_convertible<U &&, T>::value,
    2032                 :             :                   "T must be move constructible and convertible from U");
    2033                 :             :     return has_value() ? **this : static_cast<T>(std::forward<U>(u));
    2034                 :             :   }
    2035                 :             : 
    2036                 :             :   /// Destroys the stored value if one exists, making the optional empty
    2037                 :             :   void reset() noexcept { m_value = nullptr; }
    2038                 :             : 
    2039                 :             : private:
    2040                 :             :   T *m_value;
    2041                 :             : }; // namespace tl
    2042                 :             : 
    2043                 :             : 
    2044                 :             : 
    2045                 :             : } // namespace tl
    2046                 :             : 
    2047                 :             : namespace std {
    2048                 :             : // TODO SFINAE
    2049                 :             : template <class T> struct hash<tl::optional<T>> {
    2050                 :       41658 :   ::std::size_t operator()(const tl::optional<T> &o) const {
    2051                 :       41658 :     if (!o.has_value())
    2052                 :             :       return 0;
    2053                 :             : 
    2054                 :       41472 :     return std::hash<tl::detail::remove_const_t<T>>()(*o);
    2055                 :             :   }
    2056                 :             : };
    2057                 :             : } // namespace std
    2058                 :             : 
    2059                 :             : #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.