LCOV - code coverage report
Current view: top level - gcc/rust/util - optional.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.1 % 209 180
Test Date: 2026-02-28 14:20:25 Functions: 71.9 % 342 246
Legend: Lines:     hit not hit

            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              : 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              :   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       265418 : 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       291906 :   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      8625065 :   TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
     357      8546155 :       : m_dummy(), m_has_value(false) {}
     358              : 
     359              :   template <class... U>
     360      1251983 :   TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
     361      1708097 :       : m_value(std::forward<U>(u)...), m_has_value(true) {}
     362              : 
     363      7279290 :   ~optional_storage_base() {
     364      2987265 :     if (m_has_value) {
     365      3393839 :       m_value.~T();
     366              :       m_has_value = false;
     367              :     }
     368          444 :   }
     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       264792 :   TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
     382       264792 :       : m_dummy(), m_has_value(false) {}
     383              : 
     384              :   template <class... U>
     385      7753545 :   TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
     386      7707273 :       : 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     21856467 : template <class T> struct optional_operations_base : optional_storage_base<T> {
     402      9850765 :   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      3762149 :   template <class... Args> void construct(Args &&... args) {
     410      4286657 :     new (std::addressof(this->m_value)) T(std::forward<Args>(args)...);
     411      3759202 :     this->m_has_value = true;
     412      3141872 :   }
     413              : 
     414       163191 :   template <class Opt> void assign(Opt &&rhs) {
     415       163191 :     if (this->has_value()) {
     416          667 :       if (rhs.has_value()) {
     417         3583 :         this->m_value = std::forward<Opt>(rhs).get();
     418              :       } else {
     419           33 :         this->m_value.~T();
     420           33 :         this->m_has_value = false;
     421              :       }
     422              :     }
     423              : 
     424       162524 :     else if (rhs.has_value()) {
     425       136567 :       construct(std::forward<Opt>(rhs).get());
     426              :     }
     427       163191 :   }
     428              : 
     429      8124223 :   bool has_value() const { return this->m_has_value; }
     430              : 
     431       998655 :   TL_OPTIONAL_11_CONSTEXPR T &get() & { return this->m_value; }
     432      2344355 :   TL_OPTIONAL_11_CONSTEXPR const T &get() const & { return this->m_value; }
     433       111820 :   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       264792 : struct optional_copy_base : optional_operations_base<T> {
     443      7726251 :   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     12966987 : struct optional_copy_base<T, false> : optional_operations_base<T> {
     449      2124658 :   using optional_operations_base<T>::optional_operations_base;
     450              : 
     451      2328634 :   optional_copy_base() = default;
     452      6296431 :   optional_copy_base(const optional_copy_base &rhs)
     453      6296431 :   : optional_operations_base<T>() {
     454      6296431 :     if (rhs.has_value()) {
     455      2473665 :       this->construct(rhs.get());
     456              :     } else {
     457          134 :       this->m_has_value = false;
     458              :     }
     459      6296431 :   }
     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       264792 : struct optional_move_base : optional_copy_base<T> {
     474      7726251 :   using optional_copy_base<T>::optional_copy_base;
     475              : };
     476              : #else
     477              : template <class T, bool = false> struct optional_move_base;
     478              : #endif
     479     12966987 : template <class T> struct optional_move_base<T, false> : optional_copy_base<T> {
     480      2124658 :   using optional_copy_base<T>::optional_copy_base;
     481              : 
     482        54907 :   optional_move_base() = default;
     483      1763600 :   optional_move_base(const optional_move_base &rhs) = default;
     484              : 
     485      2273727 :   optional_move_base(optional_move_base &&rhs) noexcept(
     486      2273727 :       std::is_nothrow_move_constructible<T>::value) {
     487      2247084 :     if (rhs.has_value()) {
     488       998655 :       this->construct(std::move(rhs.get()));
     489              :     } else {
     490       253618 :       this->m_has_value = false;
     491              :     }
     492      1896057 :   }
     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       264792 : struct optional_copy_assign_base : optional_move_base<T> {
     502      7705200 :   using optional_move_base<T>::optional_move_base;
     503              : };
     504              : 
     505              : template <class T>
     506     12966987 : struct optional_copy_assign_base<T, false> : optional_move_base<T> {
     507      2145709 :   using optional_move_base<T>::optional_move_base;
     508              : 
     509        54907 :   optional_copy_assign_base() = default;
     510     11044120 :   optional_copy_assign_base(const optional_copy_assign_base &rhs) = default;
     511              : 
     512      2407318 :   optional_copy_assign_base(optional_copy_assign_base &&rhs) = default;
     513        25394 :   optional_copy_assign_base &operator=(const optional_copy_assign_base &rhs) {
     514        25394 :     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       264792 : struct optional_move_assign_base : optional_copy_assign_base<T> {
     531      7703635 :   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     12966987 : struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
     539      2145709 :   using optional_copy_assign_base<T>::optional_copy_assign_base;
     540              : 
     541        54907 :   optional_move_assign_base() = default;
     542     11044120 :   optional_move_assign_base(const optional_move_assign_base &rhs) = default;
     543              : 
     544      4314553 :   optional_move_assign_base(optional_move_assign_base &&rhs) = default;
     545              : 
     546              :   optional_move_assign_base &
     547        26450 :   operator=(const optional_move_assign_base &rhs) = default;
     548              : 
     549              :   optional_move_assign_base &
     550       135986 :   operator=(optional_move_assign_base &&rhs) noexcept(
     551              :       std::is_nothrow_move_constructible<T>::value
     552              :           &&std::is_nothrow_move_assignable<T>::value) {
     553       135986 :     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        40870 :   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        39764 :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
     705         1106 :                        : 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       107137 :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
     780       107137 :     return optional_map_impl(std::move(*this), std::forward<F>(f));
     781              :   }
     782              : 
     783              :   template <class F> constexpr auto map(F &&f) const & {
     784              :     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           26 :   template <class F, class U> U map_or(F &&f, U &&u) & {
     935           21 :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
     936            5 :                        : 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       215259 :   template <class F, class U> U map_or(F &&f, U &&u) const & {
     945       106001 :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
     946       215259 :                        : std::forward<U>(u);
     947       109258 :   }
     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        52015 :   constexpr optional() noexcept = default;
    1039              : 
    1040       190133 :   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      4767674 :   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      2533655 :   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            0 :   constexpr explicit optional(
    1057              :       detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>,
    1058              :       Args &&... args)
    1059            0 :       : 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      9002198 :   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        12730 :   optional(const optional<U> &rhs) {
    1088        12730 :     if (rhs.has_value()) {
    1089            1 :       this->construct(*rhs);
    1090              :     }
    1091        12730 :   }
    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         6498 :   optional(optional<U> &&rhs) {
    1107         6498 :     if (rhs.has_value()) {
    1108         6441 :       this->construct(std::move(*rhs));
    1109              :     }
    1110         6498 :   }
    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      8411226 :   ~optional() = default;
    1123              : 
    1124              :   /// Assignment to empty.
    1125              :   ///
    1126              :   /// Destroys the current value if there is one.
    1127         4034 :   optional &operator=(nullopt_t) noexcept {
    1128         4034 :     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        25394 :   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       135986 :   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       165391 :   optional &operator=(U &&u) {
    1152       165391 :     if (has_value()) {
    1153           32 :       this->m_value = std::forward<U>(u);
    1154              :     } else {
    1155       165360 :       this->construct(std::forward<U>(u));
    1156              :     }
    1157              : 
    1158       139028 :     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        96211 :   constexpr const T *operator->() const {
    1252              :     // constexpr function must only contain a return statement in C++11
    1253              : #ifdef TL_OPTIONAL_CXX14
    1254              :     // undefined behavior if we don't have a value
    1255            0 :     rust_assert(has_value ());
    1256              : #endif
    1257              : 
    1258        96211 :     return std::addressof(this->m_value);
    1259              :   }
    1260              : 
    1261       587072 :   TL_OPTIONAL_11_CONSTEXPR T *operator->() {
    1262              :     // constexpr function must only contain a return statement in C++11
    1263              : #ifdef TL_OPTIONAL_CXX14
    1264              :     // undefined behavior if we don't have a value
    1265            0 :     rust_assert(has_value ());
    1266              : #endif
    1267              : 
    1268       587072 :     return std::addressof(this->m_value);
    1269              :   }
    1270              : 
    1271              :   /// Returns the stored value
    1272      5494940 :   TL_OPTIONAL_11_CONSTEXPR T &operator*() &
    1273              :   {
    1274              :     // constexpr function must only contain a return statement in C++11
    1275              : #ifdef TL_OPTIONAL_CXX14
    1276              :     // undefined behavior if we don't have a value
    1277            0 :     rust_assert(has_value ());
    1278              : #endif
    1279              : 
    1280      5494940 :     return this->m_value;
    1281              :   }
    1282              : 
    1283       219708 :   constexpr const T &operator*() const &
    1284              :   {
    1285              :     // constexpr function must only contain a return statement in C++11
    1286              : #ifdef TL_OPTIONAL_CXX14
    1287              :     // undefined behavior if we don't have a value
    1288            0 :     rust_assert(has_value ());
    1289              : #endif
    1290              : 
    1291       219708 :     return this->m_value;
    1292              :   }
    1293              : 
    1294       118246 :   TL_OPTIONAL_11_CONSTEXPR T &&operator*() &&
    1295              :   {
    1296              :     // constexpr function must only contain a return statement in C++11
    1297              : #ifdef TL_OPTIONAL_CXX14
    1298              :     // undefined behavior if we don't have a value
    1299            0 :     rust_assert(has_value ());
    1300              : #endif
    1301              : 
    1302       118246 :     return std::move(this->m_value);
    1303              :   }
    1304              : 
    1305              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1306              :   constexpr const T &&operator*() const && { return std::move(this->m_value); }
    1307              : #endif
    1308              : 
    1309              :   /// Returns whether or not the optional has a value
    1310     14108083 :   constexpr bool has_value() const noexcept { return this->m_has_value; }
    1311              : 
    1312      6534294 :   constexpr explicit operator bool() const noexcept {
    1313      6419573 :     return this->m_has_value;
    1314              :   }
    1315              : 
    1316              :   /// Returns the contained value if there is one, otherwise throws bad_optional_access
    1317      6609183 :   TL_OPTIONAL_11_CONSTEXPR T &value() & {
    1318      6609183 :     if (has_value())
    1319      6609183 :       return this->m_value;
    1320              : 
    1321            0 :     gcc_unreachable();
    1322              :   }
    1323       171544 :   TL_OPTIONAL_11_CONSTEXPR const T &value() const & {
    1324       171544 :     if (has_value())
    1325       171544 :       return this->m_value;
    1326              : 
    1327            0 :     gcc_unreachable();
    1328              :   }
    1329        26558 :   TL_OPTIONAL_11_CONSTEXPR T &&value() && {
    1330        26558 :     if (has_value())
    1331        26558 :       return std::move(this->m_value);
    1332              : 
    1333            0 :     gcc_unreachable();
    1334              :   }
    1335              : 
    1336              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1337              :   TL_OPTIONAL_11_CONSTEXPR const T &&value() const && {
    1338              :     if (has_value())
    1339              :       return std::move(this->m_value);
    1340              : 
    1341              :     gcc_unreachable();
    1342              :   }
    1343              : #endif
    1344              : 
    1345              :   /// Returns the stored value if there is one, otherwise returns `u`
    1346              :   template <class U> constexpr T value_or(U &&u) const & {
    1347              :     static_assert(std::is_copy_constructible<T>::value &&
    1348              :                       std::is_convertible<U &&, T>::value,
    1349              :                   "T must be copy constructible and convertible from U");
    1350              :     return has_value() ? **this : static_cast<T>(std::forward<U>(u));
    1351              :   }
    1352              : 
    1353          374 :   template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && {
    1354              :     static_assert(std::is_move_constructible<T>::value &&
    1355              :                       std::is_convertible<U &&, T>::value,
    1356              :                   "T must be move constructible and convertible from U");
    1357          374 :     return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(u));
    1358              :   }
    1359              : 
    1360              :   /// Destroys the stored value if one exists, making the optional empty
    1361              :   void reset() noexcept {
    1362              :     if (has_value()) {
    1363              :       this->m_value.~T();
    1364              :       this->m_has_value = false;
    1365              :     }
    1366              :   }
    1367              : };
    1368              : 
    1369              : /// Compares two optional objects
    1370              : template <class T, class U>
    1371         3897 : inline constexpr bool operator==(const optional<T> &lhs,
    1372              :                                  const optional<U> &rhs) {
    1373         3897 :   return lhs.has_value() == rhs.has_value() &&
    1374         3897 :          (!lhs.has_value() || *lhs == *rhs);
    1375              : }
    1376              : template <class T, class U>
    1377              : inline constexpr bool operator!=(const optional<T> &lhs,
    1378              :                                  const optional<U> &rhs) {
    1379              :   return lhs.has_value() != rhs.has_value() ||
    1380              :          (lhs.has_value() && *lhs != *rhs);
    1381              : }
    1382              : template <class T, class U>
    1383              : inline constexpr bool operator<(const optional<T> &lhs,
    1384              :                                 const optional<U> &rhs) {
    1385              :   return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
    1386              : }
    1387              : template <class T, class U>
    1388              : inline constexpr bool operator>(const optional<T> &lhs,
    1389              :                                 const optional<U> &rhs) {
    1390              :   return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
    1391              : }
    1392              : template <class T, class U>
    1393              : inline constexpr bool operator<=(const optional<T> &lhs,
    1394              :                                  const optional<U> &rhs) {
    1395              :   return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
    1396              : }
    1397              : template <class T, class U>
    1398              : inline constexpr bool operator>=(const optional<T> &lhs,
    1399              :                                  const optional<U> &rhs) {
    1400              :   return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
    1401              : }
    1402              : 
    1403              : /// Compares an optional to a `nullopt`
    1404              : template <class T>
    1405        21191 : inline constexpr bool operator==(const optional<T> &lhs, nullopt_t) noexcept {
    1406        21191 :   return !lhs.has_value();
    1407              : }
    1408              : template <class T>
    1409              : inline constexpr bool operator==(nullopt_t, const optional<T> &rhs) noexcept {
    1410              :   return !rhs.has_value();
    1411              : }
    1412              : template <class T>
    1413           32 : inline constexpr bool operator!=(const optional<T> &lhs, nullopt_t) noexcept {
    1414           32 :   return lhs.has_value();
    1415              : }
    1416              : template <class T>
    1417              : inline constexpr bool operator!=(nullopt_t, const optional<T> &rhs) noexcept {
    1418              :   return rhs.has_value();
    1419              : }
    1420              : template <class T>
    1421              : inline constexpr bool operator<(const optional<T> &, nullopt_t) noexcept {
    1422              :   return false;
    1423              : }
    1424              : template <class T>
    1425              : inline constexpr bool operator<(nullopt_t, const optional<T> &rhs) noexcept {
    1426              :   return rhs.has_value();
    1427              : }
    1428              : template <class T>
    1429              : inline constexpr bool operator<=(const optional<T> &lhs, nullopt_t) noexcept {
    1430              :   return !lhs.has_value();
    1431              : }
    1432              : template <class T>
    1433              : inline constexpr bool operator<=(nullopt_t, const optional<T> &) noexcept {
    1434              :   return true;
    1435              : }
    1436              : template <class T>
    1437              : inline constexpr bool operator>(const optional<T> &lhs, nullopt_t) noexcept {
    1438              :   return lhs.has_value();
    1439              : }
    1440              : template <class T>
    1441              : inline constexpr bool operator>(nullopt_t, const optional<T> &) noexcept {
    1442              :   return false;
    1443              : }
    1444              : template <class T>
    1445              : inline constexpr bool operator>=(const optional<T> &, nullopt_t) noexcept {
    1446              :   return true;
    1447              : }
    1448              : template <class T>
    1449              : inline constexpr bool operator>=(nullopt_t, const optional<T> &rhs) noexcept {
    1450              :   return !rhs.has_value();
    1451              : }
    1452              : 
    1453              : /// Compares the optional with a value.
    1454              : template <class T, class U>
    1455        62591 : inline constexpr bool operator==(const optional<T> &lhs, const U &rhs) {
    1456        62591 :   return lhs.has_value() ? *lhs == rhs : false;
    1457              : }
    1458              : template <class T, class U>
    1459              : inline constexpr bool operator==(const U &lhs, const optional<T> &rhs) {
    1460              :   return rhs.has_value() ? lhs == *rhs : false;
    1461              : }
    1462              : template <class T, class U>
    1463           22 : inline constexpr bool operator!=(const optional<T> &lhs, const U &rhs) {
    1464           22 :   return lhs.has_value() ? *lhs != rhs : true;
    1465              : }
    1466              : template <class T, class U>
    1467              : inline constexpr bool operator!=(const U &lhs, const optional<T> &rhs) {
    1468              :   return rhs.has_value() ? lhs != *rhs : true;
    1469              : }
    1470              : template <class T, class U>
    1471              : inline constexpr bool operator<(const optional<T> &lhs, const U &rhs) {
    1472              :   return lhs.has_value() ? *lhs < rhs : true;
    1473              : }
    1474              : template <class T, class U>
    1475              : inline constexpr bool operator<(const U &lhs, const optional<T> &rhs) {
    1476              :   return rhs.has_value() ? lhs < *rhs : false;
    1477              : }
    1478              : template <class T, class U>
    1479              : inline constexpr bool operator<=(const optional<T> &lhs, const U &rhs) {
    1480              :   return lhs.has_value() ? *lhs <= rhs : true;
    1481              : }
    1482              : template <class T, class U>
    1483              : inline constexpr bool operator<=(const U &lhs, const optional<T> &rhs) {
    1484              :   return rhs.has_value() ? lhs <= *rhs : false;
    1485              : }
    1486              : template <class T, class U>
    1487              : inline constexpr bool operator>(const optional<T> &lhs, const U &rhs) {
    1488              :   return lhs.has_value() ? *lhs > rhs : false;
    1489              : }
    1490              : template <class T, class U>
    1491              : inline constexpr bool operator>(const U &lhs, const optional<T> &rhs) {
    1492              :   return rhs.has_value() ? lhs > *rhs : true;
    1493              : }
    1494              : template <class T, class U>
    1495              : inline constexpr bool operator>=(const optional<T> &lhs, const U &rhs) {
    1496              :   return lhs.has_value() ? *lhs >= rhs : false;
    1497              : }
    1498              : template <class T, class U>
    1499              : inline constexpr bool operator>=(const U &lhs, const optional<T> &rhs) {
    1500              :   return rhs.has_value() ? lhs >= *rhs : true;
    1501              : }
    1502              : 
    1503              : template <class T,
    1504              :           detail::enable_if_t<std::is_move_constructible<T>::value> * = nullptr,
    1505              :           detail::enable_if_t<detail::is_swappable<T>::value> * = nullptr>
    1506              : void swap(optional<T> &lhs,
    1507              :           optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
    1508              :   return lhs.swap(rhs);
    1509              : }
    1510              : 
    1511              : namespace detail {
    1512              : struct i_am_secret {};
    1513              : } // namespace detail
    1514              : 
    1515              : template <class T = detail::i_am_secret, class U,
    1516              :           class Ret =
    1517              :               detail::conditional_t<std::is_same<T, detail::i_am_secret>::value,
    1518              :                                     detail::decay_t<U>, T>>
    1519              : inline constexpr optional<Ret> make_optional(U &&v) {
    1520              :   return optional<Ret>(std::forward<U>(v));
    1521              : }
    1522              : 
    1523              : template <class T, class... Args>
    1524            0 : inline constexpr optional<T> make_optional(Args &&... args) {
    1525            0 :   return optional<T>(in_place, std::forward<Args>(args)...);
    1526              : }
    1527              : template <class T, class U, class... Args>
    1528              : inline constexpr optional<T> make_optional(std::initializer_list<U> il,
    1529              :                                            Args &&... args) {
    1530              :   return optional<T>(in_place, il, std::forward<Args>(args)...);
    1531              : }
    1532              : 
    1533              : #if __cplusplus >= 201703L
    1534              : template <class T> optional(T)->optional<T>;
    1535              : #endif
    1536              : 
    1537              : /// \exclude
    1538              : namespace detail {
    1539              : #ifdef TL_OPTIONAL_CXX14
    1540              : template <class Opt, class F,
    1541              :           class Ret = decltype(detail::invoke(std::declval<F>(),
    1542              :                                               *std::declval<Opt>())),
    1543              :           detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
    1544        13335 : constexpr auto optional_map_impl(Opt &&opt, F &&f) {
    1545        13335 :   return opt.has_value()
    1546        16440 :              ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
    1547        13335 :              : optional<Ret>(nullopt);
    1548              : }
    1549              : 
    1550              : template <class Opt, class F,
    1551              :           class Ret = decltype(detail::invoke(std::declval<F>(),
    1552              :                                               *std::declval<Opt>())),
    1553              :           detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
    1554        95151 : auto optional_map_impl(Opt &&opt, F &&f) {
    1555        95151 :   if (opt.has_value()) {
    1556        94103 :     detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
    1557        94103 :     return make_optional(monostate{});
    1558              :   }
    1559              : 
    1560         1048 :   return optional<monostate>(nullopt);
    1561              : }
    1562              : #else
    1563              : template <class Opt, class F,
    1564              :           class Ret = decltype(detail::invoke(std::declval<F>(),
    1565              :                                               *std::declval<Opt>())),
    1566              :           detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
    1567              : 
    1568              : constexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional<Ret> {
    1569              :   return opt.has_value()
    1570              :              ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
    1571              :              : optional<Ret>(nullopt);
    1572              : }
    1573              : 
    1574              : template <class Opt, class F,
    1575              :           class Ret = decltype(detail::invoke(std::declval<F>(),
    1576              :                                               *std::declval<Opt>())),
    1577              :           detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
    1578              : 
    1579              : auto optional_map_impl(Opt &&opt, F &&f) -> optional<monostate> {
    1580              :   if (opt.has_value()) {
    1581              :     detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
    1582              :     return monostate{};
    1583              :   }
    1584              : 
    1585              :   return nullopt;
    1586              : }
    1587              : #endif
    1588              : } // namespace detail
    1589              : 
    1590              : /// Specialization for when `T` is a reference. `optional<T&>` acts similarly
    1591              : /// to a `T*`, but provides more operations and shows intent more clearly.
    1592              : template <class T> class optional<T &> {
    1593              : public:
    1594              : // The different versions for C++14 and 11 are needed because deduced return
    1595              : // types are not SFINAE-safe. This provides better support for things like
    1596              : // generic lambdas. C.f.
    1597              : // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
    1598              : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
    1599              :     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
    1600              : 
    1601              :   /// Carries out some operation which returns an optional on the stored
    1602              :   /// object if there is one.
    1603              :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {
    1604              :     using result = detail::invoke_result_t<F, T &>;
    1605              :     static_assert(detail::is_optional<result>::value,
    1606              :                   "F must return an optional");
    1607              : 
    1608              :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1609              :                        : result(nullopt);
    1610              :   }
    1611              : 
    1612        23703 :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {
    1613              :     using result = detail::invoke_result_t<F, T &>;
    1614              :     static_assert(detail::is_optional<result>::value,
    1615              :                   "F must return an optional");
    1616              : 
    1617        23703 :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1618        23703 :                        : result(nullopt);
    1619              :   }
    1620              : 
    1621              :   template <class F> constexpr auto and_then(F &&f) const & {
    1622              :     using result = detail::invoke_result_t<F, const T &>;
    1623              :     static_assert(detail::is_optional<result>::value,
    1624              :                   "F must return an optional");
    1625              : 
    1626              :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1627              :                        : result(nullopt);
    1628              :   }
    1629              : 
    1630              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1631              :   template <class F> constexpr auto and_then(F &&f) const && {
    1632              :     using result = detail::invoke_result_t<F, const T &>;
    1633              :     static_assert(detail::is_optional<result>::value,
    1634              :                   "F must return an optional");
    1635              : 
    1636              :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1637              :                        : result(nullopt);
    1638              :   }
    1639              : #endif
    1640              : #else
    1641              :   /// Carries out some operation which returns an optional on the stored
    1642              :   /// object if there is one.
    1643              :   template <class F>
    1644              :   TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {
    1645              :     using result = detail::invoke_result_t<F, T &>;
    1646              :     static_assert(detail::is_optional<result>::value,
    1647              :                   "F must return an optional");
    1648              : 
    1649              :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1650              :                        : result(nullopt);
    1651              :   }
    1652              : 
    1653              :   template <class F>
    1654              :   TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) && {
    1655              :     using result = detail::invoke_result_t<F, T &>;
    1656              :     static_assert(detail::is_optional<result>::value,
    1657              :                   "F must return an optional");
    1658              : 
    1659              :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1660              :                        : result(nullopt);
    1661              :   }
    1662              : 
    1663              :   template <class F>
    1664              :   constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {
    1665              :     using result = detail::invoke_result_t<F, const T &>;
    1666              :     static_assert(detail::is_optional<result>::value,
    1667              :                   "F must return an optional");
    1668              : 
    1669              :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1670              :                        : result(nullopt);
    1671              :   }
    1672              : 
    1673              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1674              :   template <class F>
    1675              :   constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const && {
    1676              :     using result = detail::invoke_result_t<F, const T &>;
    1677              :     static_assert(detail::is_optional<result>::value,
    1678              :                   "F must return an optional");
    1679              : 
    1680              :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
    1681              :                        : result(nullopt);
    1682              :   }
    1683              : #endif
    1684              : #endif
    1685              : 
    1686              : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
    1687              :     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
    1688              :   /// Carries out some operation on the stored object if there is one.
    1689              :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {
    1690              :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1691              :   }
    1692              : 
    1693         1349 :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
    1694         1349 :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1695              :   }
    1696              : 
    1697              :   template <class F> constexpr auto map(F &&f) const & {
    1698              :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1699              :   }
    1700              : 
    1701              :   template <class F> constexpr auto map(F &&f) const && {
    1702              :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1703              :   }
    1704              : #else
    1705              :   /// Carries out some operation on the stored object if there is one.
    1706              :   template <class F>
    1707              :   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &>(),
    1708              :                                                      std::declval<F &&>()))
    1709              :   map(F &&f) & {
    1710              :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1711              :   }
    1712              : 
    1713              :   template <class F>
    1714              :   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &&>(),
    1715              :                                                      std::declval<F &&>()))
    1716              :   map(F &&f) && {
    1717              :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1718              :   }
    1719              : 
    1720              :   template <class F>
    1721              :   constexpr decltype(detail::optional_map_impl(std::declval<const optional &>(),
    1722              :                                       std::declval<F &&>()))
    1723              :   map(F &&f) const & {
    1724              :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1725              :   }
    1726              : 
    1727              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1728              :   template <class F>
    1729              :   constexpr decltype(detail::optional_map_impl(std::declval<const optional &&>(),
    1730              :                                       std::declval<F &&>()))
    1731              :   map(F &&f) const && {
    1732              :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1733              :   }
    1734              : #endif
    1735              : #endif
    1736              : 
    1737              : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
    1738              :     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
    1739              :   /// Carries out some operation on the stored object if there is one.
    1740              :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & {
    1741              :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1742              :   }
    1743              : 
    1744              :   template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && {
    1745              :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1746              :   }
    1747              : 
    1748              :   template <class F> constexpr auto transform(F&& f) const & {
    1749              :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1750              :   }
    1751              : 
    1752              :   template <class F> constexpr auto transform(F&& f) const && {
    1753              :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1754              :   }
    1755              : #else
    1756              :   /// Carries out some operation on the stored object if there is one.
    1757              :   template <class F>
    1758              :   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(),
    1759              :     std::declval<F&&>()))
    1760              :     transform(F&& f) & {
    1761              :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1762              :   }
    1763              : 
    1764              :   /// \group map
    1765              :   /// \synopsis template <class F> auto transform(F &&f) &&;
    1766              :   template <class F>
    1767              :   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(),
    1768              :     std::declval<F&&>()))
    1769              :     transform(F&& f) && {
    1770              :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1771              :   }
    1772              : 
    1773              :   template <class F>
    1774              :   constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(),
    1775              :     std::declval<F&&>()))
    1776              :     transform(F&& f) const & {
    1777              :     return detail::optional_map_impl(*this, std::forward<F>(f));
    1778              :   }
    1779              : 
    1780              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1781              :   template <class F>
    1782              :   constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(),
    1783              :     std::declval<F&&>()))
    1784              :     transform(F&& f) const && {
    1785              :     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
    1786              :   }
    1787              : #endif
    1788              : #endif
    1789              : 
    1790              :   /// Calls `f` if the optional is empty
    1791              :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
    1792              :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
    1793              :     if (has_value())
    1794              :       return *this;
    1795              : 
    1796              :     std::forward<F>(f)();
    1797              :     return nullopt;
    1798              :   }
    1799              : 
    1800              :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
    1801              :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
    1802              :     return has_value() ? *this : std::forward<F>(f)();
    1803              :   }
    1804              : 
    1805              :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
    1806              :   optional<T> or_else(F &&f) && {
    1807              :     if (has_value())
    1808              :       return std::move(*this);
    1809              : 
    1810              :     std::forward<F>(f)();
    1811              :     return nullopt;
    1812              :   }
    1813              : 
    1814              :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
    1815              :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {
    1816              :     return has_value() ? std::move(*this) : std::forward<F>(f)();
    1817              :   }
    1818              : 
    1819              :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
    1820              :   optional<T> or_else(F &&f) const & {
    1821              :     if (has_value())
    1822              :       return *this;
    1823              : 
    1824              :     std::forward<F>(f)();
    1825              :     return nullopt;
    1826              :   }
    1827              : 
    1828              :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
    1829              :   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {
    1830              :     return has_value() ? *this : std::forward<F>(f)();
    1831              :   }
    1832              : 
    1833              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1834              :   template <class F, detail::enable_if_ret_void<F> * = nullptr>
    1835              :   optional<T> or_else(F &&f) const && {
    1836              :     if (has_value())
    1837              :       return std::move(*this);
    1838              : 
    1839              :     std::forward<F>(f)();
    1840              :     return nullopt;
    1841              :   }
    1842              : 
    1843              :   template <class F, detail::disable_if_ret_void<F> * = nullptr>
    1844              :   optional<T> or_else(F &&f) const && {
    1845              :     return has_value() ? std::move(*this) : std::forward<F>(f)();
    1846              :   }
    1847              : #endif
    1848              : 
    1849              :   /// Maps the stored value with `f` if there is one, otherwise returns `u`
    1850              :   template <class F, class U> U map_or(F &&f, U &&u) & {
    1851              :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1852              :                        : std::forward<U>(u);
    1853              :   }
    1854              : 
    1855              :   template <class F, class U> U map_or(F &&f, U &&u) && {
    1856              :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
    1857              :                        : std::forward<U>(u);
    1858              :   }
    1859              : 
    1860              :   template <class F, class U> U map_or(F &&f, U &&u) const & {
    1861              :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1862              :                        : std::forward<U>(u);
    1863              :   }
    1864              : 
    1865              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1866              :   template <class F, class U> U map_or(F &&f, U &&u) const && {
    1867              :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
    1868              :                        : std::forward<U>(u);
    1869              :   }
    1870              : #endif
    1871              : 
    1872              :   /// Maps the stored value with `f` if there is one, otherwise calls
    1873              :   /// `u` and returns the result.
    1874              :   template <class F, class U>
    1875              :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {
    1876              :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1877              :                        : std::forward<U>(u)();
    1878              :   }
    1879              : 
    1880              :   template <class F, class U>
    1881              :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {
    1882              :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
    1883              :                        : std::forward<U>(u)();
    1884              :   }
    1885              : 
    1886              :   template <class F, class U>
    1887              :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {
    1888              :     return has_value() ? detail::invoke(std::forward<F>(f), **this)
    1889              :                        : std::forward<U>(u)();
    1890              :   }
    1891              : 
    1892              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1893              :   template <class F, class U>
    1894              :   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {
    1895              :     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
    1896              :                        : std::forward<U>(u)();
    1897              :   }
    1898              : #endif
    1899              : 
    1900              :   /// Returns `u` if `*this` has a value, otherwise an empty optional.
    1901              :   template <class U>
    1902              :   constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {
    1903              :     using result = optional<detail::decay_t<U>>;
    1904              :     return has_value() ? result{u} : result{nullopt};
    1905              :   }
    1906              : 
    1907              :   /// Returns `rhs` if `*this` is empty, otherwise the current value.
    1908              :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {
    1909              :     return has_value() ? *this : rhs;
    1910              :   }
    1911              : 
    1912              :   constexpr optional disjunction(const optional &rhs) const & {
    1913              :     return has_value() ? *this : rhs;
    1914              :   }
    1915              : 
    1916              :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {
    1917              :     return has_value() ? std::move(*this) : rhs;
    1918              :   }
    1919              : 
    1920              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1921              :   constexpr optional disjunction(const optional &rhs) const && {
    1922              :     return has_value() ? std::move(*this) : rhs;
    1923              :   }
    1924              : #endif
    1925              : 
    1926              :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {
    1927              :     return has_value() ? *this : std::move(rhs);
    1928              :   }
    1929              : 
    1930              :   constexpr optional disjunction(optional &&rhs) const & {
    1931              :     return has_value() ? *this : std::move(rhs);
    1932              :   }
    1933              : 
    1934              :   TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {
    1935              :     return has_value() ? std::move(*this) : std::move(rhs);
    1936              :   }
    1937              : 
    1938              : #ifndef TL_OPTIONAL_NO_CONSTRR
    1939              :   constexpr optional disjunction(optional &&rhs) const && {
    1940              :     return has_value() ? std::move(*this) : std::move(rhs);
    1941              :   }
    1942              : #endif
    1943              : 
    1944              :   /// Takes the value out of the optional, leaving it empty
    1945              :   optional take() {
    1946              :     optional ret = std::move(*this);
    1947              :     reset();
    1948              :     return ret;
    1949              :   }
    1950              : 
    1951              :   using value_type = T &;
    1952              : 
    1953              :   /// Constructs an optional that does not contain a value.
    1954        40590 :   constexpr optional() noexcept : m_value(nullptr) {}
    1955              : 
    1956              :   constexpr optional(nullopt_t) noexcept : m_value(nullptr) {}
    1957              : 
    1958              :   /// Copy constructor
    1959              :   ///
    1960              :   /// If `rhs` contains a value, the stored value is direct-initialized with
    1961              :   /// it. Otherwise, the constructed optional is empty.
    1962              :   TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) noexcept = default;
    1963              : 
    1964              :   /// Move constructor
    1965              :   ///
    1966              :   /// If `rhs` contains a value, the stored value is direct-initialized with
    1967              :   /// it. Otherwise, the constructed optional is empty.
    1968              :   TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;
    1969              : 
    1970              :   /// Constructs the stored value with `u`.
    1971              :   template <class U = T,
    1972              :             detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
    1973              :                 * = nullptr>
    1974      1776712 :   constexpr optional(U &&u)  noexcept : m_value(std::addressof(u)) {
    1975              :     static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
    1976           53 :   }
    1977              : 
    1978              :   template <class U>
    1979              :   constexpr explicit optional(const optional<U> &rhs) noexcept : optional(*rhs) {}
    1980              : 
    1981              :   /// No-op
    1982              :   ~optional() = default;
    1983              : 
    1984              :   /// Assignment to empty.
    1985              :   ///
    1986              :   /// Destroys the current value if there is one.
    1987              :   optional &operator=(nullopt_t) noexcept {
    1988              :     m_value = nullptr;
    1989              :     return *this;
    1990              :   }
    1991              : 
    1992              :   /// Copy assignment.
    1993              :   ///
    1994              :   /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
    1995              :   /// resets the stored value in `*this`.
    1996              :   optional &operator=(const optional &rhs) = default;
    1997              : 
    1998              :   /// Rebinds this optional to `u`.
    1999              :   template <class U = T,
    2000              :             detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
    2001              :                 * = nullptr>
    2002         2800 :   optional &operator=(U &&u) {
    2003              :     static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
    2004         2800 :     m_value = std::addressof(u);
    2005            0 :     return *this;
    2006              :   }
    2007              : 
    2008              :   /// Converting copy assignment operator.
    2009              :   ///
    2010              :   /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
    2011              :   /// resets the stored value in `*this`.
    2012              :   template <class U> optional &operator=(const optional<U> &rhs) noexcept {
    2013              :     m_value = std::addressof(rhs.value());
    2014              :     return *this;
    2015              :   }
    2016              : 
    2017              :   /// Rebinds this optional to `u`.
    2018              :   template <class U = T,
    2019              :             detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
    2020              :                 * = nullptr>
    2021              :   optional &emplace(U &&u) noexcept {
    2022              :     return *this = std::forward<U>(u);
    2023              :   }
    2024              : 
    2025              :   void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); }
    2026              : 
    2027              :   /// Returns a pointer to the stored value
    2028            0 :   constexpr const T *operator->() const noexcept
    2029              :   {
    2030              :     // constexpr function must only contain a return statement in C++11
    2031              : #ifdef TL_OPTIONAL_CXX14
    2032              :     // undefined behavior if we don't have a value
    2033            0 :     rust_assert(has_value ());
    2034              : #endif
    2035              : 
    2036            0 :     return m_value;
    2037              :   }
    2038              : 
    2039        22650 :   TL_OPTIONAL_11_CONSTEXPR T *operator->() noexcept
    2040              :   {
    2041              :     // constexpr function must only contain a return statement in C++11
    2042              : #ifdef TL_OPTIONAL_CXX14
    2043              :     // undefined behavior if we don't have a value
    2044            0 :     rust_assert(has_value ());
    2045              : #endif
    2046              : 
    2047        22650 :     return m_value;
    2048              :   }
    2049              : 
    2050              :   /// Returns the stored value
    2051        69018 :   TL_OPTIONAL_11_CONSTEXPR T &operator*() noexcept {
    2052              :     // constexpr function must only contain a return statement in C++11
    2053              : #ifdef TL_OPTIONAL_CXX14
    2054              :     // undefined behavior if we don't have a value
    2055            0 :     rust_assert(has_value ());
    2056              : #endif
    2057              : 
    2058        69018 :     return *m_value;
    2059              :   }
    2060              : 
    2061            0 :   constexpr const T &operator*() const noexcept
    2062              :   {
    2063              :     // constexpr function must only contain a return statement in C++11
    2064              : #ifdef TL_OPTIONAL_CXX14
    2065              :     // undefined behavior if we don't have a value
    2066            0 :     rust_assert(has_value ());
    2067              : #endif
    2068              : 
    2069            0 :     return *m_value;
    2070              :   }
    2071              : 
    2072      4225738 :   constexpr bool has_value() const noexcept { return m_value != nullptr; }
    2073              : 
    2074       160891 :   constexpr explicit operator bool() const noexcept {
    2075       160791 :     return m_value != nullptr;
    2076              :   }
    2077              : 
    2078              :   /// Returns the contained value if there is one, otherwise throws bad_optional_access
    2079      3381428 :   TL_OPTIONAL_11_CONSTEXPR T &value() {
    2080      3381428 :     if (has_value())
    2081      3381428 :       return *m_value;
    2082              : 
    2083            0 :     gcc_unreachable();
    2084              :   }
    2085            1 :   TL_OPTIONAL_11_CONSTEXPR const T &value() const {
    2086            1 :     if (has_value())
    2087            1 :       return *m_value;
    2088              : 
    2089            0 :     gcc_unreachable();
    2090              :   }
    2091              : 
    2092              :   /// Returns the stored value if there is one, otherwise returns `u`
    2093            0 :   template <class U> constexpr T value_or(U &&u) const & noexcept {
    2094              :     static_assert(std::is_copy_constructible<T>::value &&
    2095              :                       std::is_convertible<U &&, T>::value,
    2096              :                   "T must be copy constructible and convertible from U");
    2097            0 :     return has_value() ? **this : static_cast<T>(std::forward<U>(u));
    2098              :   }
    2099              : 
    2100              :   /// \group value_or
    2101              :   template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && noexcept {
    2102              :     static_assert(std::is_move_constructible<T>::value &&
    2103              :                       std::is_convertible<U &&, T>::value,
    2104              :                   "T must be move constructible and convertible from U");
    2105              :     return has_value() ? **this : static_cast<T>(std::forward<U>(u));
    2106              :   }
    2107              : 
    2108              :   /// Destroys the stored value if one exists, making the optional empty
    2109              :   void reset() noexcept { m_value = nullptr; }
    2110              : 
    2111              : private:
    2112              :   T *m_value;
    2113              : };
    2114              : 
    2115              : 
    2116              : 
    2117              : } // namespace tl
    2118              : 
    2119              : namespace std {
    2120              : // TODO SFINAE
    2121              : template <class T> struct hash<tl::optional<T>> {
    2122        54985 :   ::std::size_t operator()(const tl::optional<T> &o) const {
    2123        54985 :     if (!o.has_value())
    2124              :       return 0;
    2125              : 
    2126        54723 :     return std::hash<tl::detail::remove_const_t<T>>()(*o);
    2127              :   }
    2128              : };
    2129              : } // namespace std
    2130              : 
    2131              : #endif
        

Generated by: LCOV version 2.4-beta

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