From 6253bac1f6a05186ff8a957dfa83ba907c385abd Mon Sep 17 00:00:00 2001 From: Simon Brand Date: Sat, 21 Oct 2017 08:12:49 +0100 Subject: [PATCH] Docs --- docs/index.md | 609 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 609 insertions(+) create mode 100644 docs/index.md diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..82a87f8 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,609 @@ +# Header file `optional.hpp` + +
#define TL_OPTIONAL_11_CONSTEXPR
+
+#define TL_OPTIONAL_MSVC_2015_CONSTEXPR
+
+namespace tl
+{
+    class monostate;
+    
+    namespace detail
+    {
+        template <class T>
+        using remove_cv_t = typename std::remove_cv<T>::type;
+        
+        template <class T>
+        using remove_const_t = typename std::remove_const<T>::type;
+        
+        template <class T>
+        using remove_volatile_t = typename std::remove_volatile<T>::type;
+        
+        template <class T>
+        using add_cv_t = typename std::add_cv<T>::type;
+        
+        template <class T>
+        using add_const_t = typename std::add_const<T>::type;
+        
+        template <class T>
+        using add_volatile_t = typename std::add_volatile<T>::type;
+        
+        template <class T>
+        using remove_reference_t = typename std::remove_reference<T>::type;
+        
+        template <class T>
+        using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
+        
+        template <class T>
+        using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
+        
+        template <class T>
+        using remove_pointer_t = typename std::remove_pointer<T>::type;
+        
+        template <class T>
+        using add_pointer_t = typename std::add_pointer<T>::type;
+        
+        template <class T>
+        using make_signed_t = typename std::make_signed<T>::type;
+        
+        template <class T>
+        using make_unsigned_t = typename std::make_unsigned<T>::type;
+        
+        template <class T>
+        using remove_extent_t = typename std::remove_extent<T>::type;
+        
+        template <class T>
+        using remove_all_extents_t = typename std::remove_all_extents<T>::type;
+        
+        template <std::size_t N, std::size_t A = N>
+        using aligned_storage_t = typename std::aligned_storage<N, A>::type;
+        
+        template <std::size_t N, class ... Ts>
+        using aligned_union_t = typename std::aligned_union<N, Ts...>::type;
+        
+        template <class T>
+        using decay_t = typename std::decay<T>::type;
+        
+        template <bool E, class T = void>
+        using enable_if_t = typename std::enable_if<E, T>::type;
+        
+        template <bool B, class T, class F>
+        using conditional_t = typename std::conditional<B, T, F>::type;
+        
+        template <class ... Ts>
+        using common_type_t = typename std::common_type<Ts...>::type;
+        
+        template <class T>
+        using underlying_type_t = typename std::underlying_type<T>::type;
+        
+        template <class T>
+        using result_of_t = typename std::result_of<T>::type;
+        
+        template <class>
+        struct conjunction;
+        
+        template <class B>
+        struct conjunction<B>;
+        
+        template <class B, class ... Bs>
+        struct conjunction<B, Bs...>;
+        
+        template <class>
+        struct voider;
+        
+        template <class ... Ts>
+        using void_t = typename voider<Ts...>::type;
+        
+        template <class T>
+        struct is_optional_impl;
+        
+        template <class T>
+        struct is_optional_impl<optional<T>>;
+        
+        template <class T>
+        using is_optional = is_optional_impl<decay_t<T>>;
+        
+        template <typename Fn, typename ... Args, typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>{}>, int=0>
+        constexpr decltype(std::mem_fn(f)(std::forward<Args>(args)...)) invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...)));
+        
+        template <typename Fn, typename ... Args, typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>{}>>
+        constexpr decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)));
+        
+        template <class F, class ... Us>
+        struct invoke_result_impl<F, decltype(invoke(std::declval<F>(), std::declval<Us>()...), void()), Us...>;
+        
+        template <class F, class ... Us>
+        using invoke_result = invoke_result_impl<F, void, Us...>;
+        
+        template <class F, class ... Us>
+        using invoke_result_t = typename invoke_result<F, Us...>::type;
+        
+        template <class U>
+        using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>;
+        
+        template <class F, class ... U>
+        struct get_invoke_optional_ret;
+        
+        template <class F, class ... U>
+        using get_invoke_ret = typename conditional_t<is_optional<F>::value, get_invoke_optional_ret<F, U...>, invoke_result<F, U...>>::type;
+        
+        template <class F, class U>
+        using get_map_return = optional<fixup_void<get_invoke_ret<F, U>>>;
+        
+        template <class F, class ... U>
+        using returns_void = std::is_void<get_invoke_ret<F, U...>>;
+        
+        template <class T>
+        using disable_if_optional = enable_if_t<!is_optional<T>::value>;
+        
+        template <class T>
+        using enable_if_optional = enable_if_t<is_optional<T>::value>;
+        
+        template <class T, class ... U>
+        using enable_if_ret_void = enable_if_t<returns_void<T&&, U...>::value>;
+        
+        template <class T, class ... U>
+        using disable_if_ret_void = enable_if_t<!returns_void<T&&, U...>::value>;
+    }
+    
+    struct in_place_t;
+    
+    constexpr in_place_t{} in_place;
+    
+    namespace detail
+    {
+        template <class T, class U>
+        using enable_forward_value = detail::enable_if_t<std::is_constructible<T, U&&>::value&&!std::is_same<detail::decay_t<U>, in_place_t>::value&&!std::is_same<optional<T>, detail::decay_t<U>>::value>;
+        
+        template <class T, class U, class Other>
+        using enable_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value&&!std::is_constructible<T, optional<U>&>::value&&!std::is_constructible<T, optional<U>&&>::value&&!std::is_constructible<T, const optional<U>&>::value&&!std::is_constructible<T, const optional<U>&&>::value&&!std::is_convertible<optional<U>&, T>::value&&!std::is_convertible<optional<U>&&, T>::value&&!std::is_convertible<const optional<U>&, T>::value&&!std::is_convertible<const optional<U>&&, T>::value>;
+        
+        template <class T, class U>
+        using enable_assign_forward = detail::enable_if_t<!std::is_same<optional<T>, detail::decay_t<U>>::value&&!detail::conjunction<std::is_scalar<T>, std::is_same<T, detail::decay_t<U>>>::value&&std::is_constructible<T, U>::value&&std::is_assignable<T&, U>::value>;
+        
+        template <class T, class U, class Other>
+        using enable_assign_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value&&std::is_assignable<T&, Other>::value&&!std::is_constructible<T, optional<U>&>::value&&!std::is_constructible<T, optional<U>&&>::value&&!std::is_constructible<T, const optional<U>&>::value&&!std::is_constructible<T, const optional<U>&&>::value&&!std::is_convertible<optional<U>&, T>::value&&!std::is_convertible<optional<U>&&, T>::value&&!std::is_convertible<const optional<U>&, T>::value&&!std::is_convertible<const optional<U>&&, T>::value&&!std::is_assignable<T&, optional<U>&>::value&&!std::is_assignable<T&, optional<U>&&>::value&&!std::is_assignable<T&, const optional<U>&>::value&&!std::is_assignable<T&, const optional<U>&&>::value>;
+        
+        namespace swap_adl_tests
+        {
+            struct tag;
+            
+            template <class T>
+            tag swap(T&, T&);
+            
+            template <class T, std::size_t N>
+            tag swap(T(&)[N] a, T(&)[N] b);
+            
+            template <class, class>
+            std::false_type can_swap(...) noexcept(false);
+            
+            template <class T, class U, class = decltype(swap(std::declval<T&>(), std::declval<U&>()))>
+            )>std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T&>(), std::declval<U&>())));
+            
+            template <class, class>
+            std::false_type uses_std(...);
+            
+            template <class T, class U>
+            std::is_same<decltype(swap(std::declval<T&>(), std::declval<U&>())), tag> uses_std(int);
+            
+            template <class T>
+            struct is_std_swap_noexcept;
+            
+            template <class T, std::size_t N>
+            struct is_std_swap_noexcept<T[N]>;
+            
+            template <class T, class U>
+            struct is_adl_swap_noexcept;
+        }
+        
+        template <class T, class U = T>
+        struct is_swappable;
+        
+        template <class T, std::size_t N>
+        struct is_swappable<T[N], T[N]>;
+        
+        template <class T, class U = T>
+        struct is_nothrow_swappable;
+    }
+    
+    struct nullopt_t;
+    
+    constexpr nullopt_t{nullopt_t::do_not_use{}, nullopt_t::do_not_use{}} nullopt;
+    
+    class bad_optional_access;
+    
+    template <class T, class U>
+    constexpr bool operator==(const optional<T>& lhs, const optional<U>& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator!=(const optional<T>& lhs, const optional<U>& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator<(const optional<T>& lhs, const optional<U>& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator>(const optional<T>& lhs, const optional<U>& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator<=(const optional<T>& lhs, const optional<U>& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator>=(const optional<T>& lhs, const optional<U>& rhs);
+    
+    template <class T>
+    constexpr bool operator==(const optional<T>& lhs, nullopt_t) noexcept;
+    
+    template <class T>
+    constexpr bool operator==(nullopt_t, const optional<T>& rhs) noexcept;
+    
+    template <class T>
+    constexpr bool operator!=(const optional<T>& lhs, nullopt_t) noexcept;
+    
+    template <class T>
+    constexpr bool operator!=(nullopt_t, const optional<T>& rhs) noexcept;
+    
+    template <class T>
+    constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
+    
+    template <class T>
+    constexpr bool operator<(nullopt_t, const optional<T>& rhs) noexcept;
+    
+    template <class T>
+    constexpr bool operator<=(const optional<T>& lhs, nullopt_t) noexcept;
+    
+    template <class T>
+    constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
+    
+    template <class T>
+    constexpr bool operator>(const optional<T>& lhs, nullopt_t) noexcept;
+    
+    template <class T>
+    constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
+    
+    template <class T>
+    constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
+    
+    template <class T>
+    constexpr bool operator>=(nullopt_t, const optional<T>& rhs) noexcept;
+    
+    template <class T, class U>
+    constexpr bool operator==(const optional<T>& lhs, const U& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator==(const U& lhs, const optional<T>& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator!=(const optional<T>& lhs, const U& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator!=(const U& lhs, const optional<T>& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator<(const optional<T>& lhs, const U& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator<(const U& lhs, const optional<T>& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator<=(const optional<T>& lhs, const U& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator<=(const U& lhs, const optional<T>& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator>(const optional<T>& lhs, const U& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator>(const U& lhs, const optional<T>& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator>=(const optional<T>& lhs, const U& rhs);
+    
+    template <class T, class U>
+    constexpr bool operator>=(const U& lhs, const optional<T>& rhs);
+    
+    template <class T, detail::enable_if_t<std::is_move_constructible<T>::value>*=nullptr, detail::enable_if_t<detail::is_swappable<T>::value>*=nullptr>
+    void swap(optional<T>& lhs, optional<T>& rhs) noexcept(noexcept(lhs.swap(rhs)));
+    
+    template <class T>
+    constexpr optional<detail::decay_t<T>> make_optional(T&& v);
+    
+    template <class T, class ... Args>
+    constexpr optional<T> make_optional(Args&&... args);
+    
+    template <class T, class U, class ... Args>
+    constexpr optional<T> make_optional(std::initializer_list<U> il, Args&&... args);
+}
+
+namespace std
+{
+}
+
+namespace tl
+{
+    namespace detail
+    {
+        template <class T, bool=::std::is_trivially_destructible<T>::value>
+        struct optional_storage_base;
+        
+        template <class T>
+        struct optional_storage_base<T, true>;
+    }
+    
+    template <class T>
+    class optional;
+}
+ +----- + +----- + +## Class template `tl::optional` + +
template <class T>
+class optional
+{
+public:
+    using value_type = T;
+    
+    constexpr optional() noexcept = default;
+    
+    constexpr optional(nullopt_t) noexcept;
+    
+    constexpr optional(const optional& rhs);
+    
+    constexpr optional(optional&& rhs) noexcept(std::is_nothrow_move_constructible<T>::value);
+    
+    template <class ... Args>
+    constexpr optional(detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>, Args&&... args);
+    
+    template <class U, class ... Args>
+    constexpr optional(detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, in_place_t>, std::initializer_list<U> il, Args&&... args);
+    
+    template <class U = T, detail::enable_if_t<std::is_convertible<U&&, T>::value>*=nullptr, detail::enable_forward_value<T, U>*=nullptr>
+    constexpr optional(U&& u);
+    
+    template <class U = T, detail::enable_if_t<!std::is_convertible<U&&, T>::value>*=nullptr, detail::enable_forward_value<T, U>*=nullptr>
+    constexpr optional(U&& u);
+    
+    template <class U, detail::enable_from_other<T, U, const U&>*=nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>*=nullptr>
+    optional(const optional<U>& rhs);
+    
+    template <class U, detail::enable_from_other<T, U, const U&>*=nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>*=nullptr>
+    optional(const optional<U>& rhs);
+    
+    template <class U, detail::enable_from_other<T, U, U&&>*=nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>*=nullptr>
+    optional(optional<U>&& rhs);
+    
+    template <class U, detail::enable_from_other<T, U, U&&>*=nullptr, detail::enable_if_t<!std::is_convertible<U&&, T>::value>*=nullptr>
+    optional(optional<U>&& rhs);
+    
+    ~optional() = default;
+    
+    optional& operator=(nullopt_t) noexcept;
+    
+    optional& operator=(const optional& rhs);
+    
+    optional& operator=(optional&& rhs) noexcept(std::is_nothrow_move_assignable<T>::value&&std::is_nothrow_move_constructible<T>::value);
+    
+    template <class U = T, detail::enable_assign_forward<T, U>*=nullptr>
+    optional& operator=(U&& u);
+    
+    template <class U, detail::enable_assign_from_other<T, U, const U&>*=nullptr>
+    optional& operator=(const optional<U>& rhs);
+    
+    template <class U, detail::enable_assign_from_other<T, U, U>*=nullptr>
+    optional& operator=(optional<U>&& rhs);
+    
+    template <class ... Args>
+    T& emplace(Args&&... args);
+    
+    template <class U, class ... Args>
+    detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, T&> emplace(std::initializer_list<U> il, Args&&... args);
+    
+    void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible<T>::value&&detail::is_nothrow_swappable<T>::value);
+    
+    constexpr const T* operator->() const;
+    
+    constexpr T* operator->();
+    
+    constexpr const T& operator*() const &;
+    
+    constexpr T& operator*() &;
+    
+    constexpr T&& operator*() &&;
+    
+    constexpr const T&& operator*() const &&;
+    
+    constexpr operator bool() const noexcept;
+    
+    constexpr bool has_value() const noexcept;
+    
+    constexpr const T& value() const &;
+    
+    constexpr T& value() &;
+    
+    constexpr T&& value() &&;
+    
+    constexpr const T&& value() const &&;
+    
+    template <class U>
+    constexpr T value_or(U&& u) const &;
+    
+    template <class U>
+    constexpr T value_or(U&& u) &&;
+    
+    void reset() noexcept;
+    
+    template <class F>
+    constexpr detail::invoke_result_t<F, T> and_then(F&& f) &;
+    template <class F>
+    constexpr detail::invoke_result_t<F, T> and_then(F&& f) const &;
+    
+    template <class F>
+    constexpr detail::invoke_result_t<F, T> and_then(F&& f) &&;
+    template <class F>
+    constexpr detail::invoke_result_t<F, T> and_then(F&& f) const &&;
+    
+    template <class F> auto map(F &&f) &;
+    template <class F> auto map(F &&f) const &;
+    
+    template <class F, detail::disable_if_optional<F>*=nullptr, detail::enable_if_ret_void<F, T&>*=nullptr>
+    detail::get_map_return<F, T&> map(F&& f) &;
+    
+    template <class F, detail::enable_if_optional<F>*=nullptr, detail::disable_if_ret_void<F, T&>*=nullptr>
+    detail::get_map_return<F, T&> map(F&& f) &;
+    
+    template <class F, detail::enable_if_optional<F>*=nullptr, detail::enable_if_ret_void<F, T&>*=nullptr>
+    detail::get_map_return<F, T&> map(F&& f) &;
+    
+    template <class F> auto map(F &&f) &;
+    template <class F> auto map(F &&f) const &&;
+    
+    template <class F, detail::disable_if_optional<F>*=nullptr, detail::enable_if_ret_void<F, T&&>*=nullptr>
+    detail::get_map_return<F, T&&> map(F&& f) &&;
+    
+    template <class F, detail::enable_if_optional<F>*=nullptr, detail::disable_if_ret_void<F, T&&>*=nullptr>
+    detail::get_map_return<F, T&&> map(F&& f) &&;
+    
+    template <class F, detail::enable_if_optional<F>*=nullptr, detail::enable_if_ret_void<F, T&&>*=nullptr>
+    detail::get_map_return<F, T&&> map(F&& f) &&;
+    
+    template <class F, detail::disable_if_optional<F>*=nullptr, detail::enable_if_ret_void<F, T const&>*=nullptr>
+    detail::get_map_return<F, T const&> map(F&& f) const &;
+    
+    template <class F, detail::enable_if_optional<F>*=nullptr, detail::disable_if_ret_void<F, T const&>*=nullptr>
+    constexpr detail::get_map_return<F, T const&> map(F&& f) const &;
+    
+    template <class F, detail::enable_if_optional<F>*=nullptr, detail::enable_if_ret_void<F, T const&>*=nullptr>
+    detail::get_map_return<F, T const&> map(F&& f) const &;
+    
+    template <class F, detail::disable_if_optional<F>*=nullptr, detail::enable_if_ret_void<F, T const&&>*=nullptr>
+    detail::get_map_return<F, T const&&> map(F&& f) const &&;
+    
+    template <class F, detail::enable_if_optional<F>*=nullptr, detail::disable_if_ret_void<F, T const&&>*=nullptr>
+    constexpr detail::get_map_return<F, T const&&> map(F&& f) const &&;
+    
+    template <class F, detail::enable_if_optional<F>*=nullptr, detail::enable_if_ret_void<F, T const&&>*=nullptr>
+    detail::get_map_return<F, T&> map(F&& f) const &&;
+    
+    template <class F> optional<T> or_else (F &&f) &;
+    template <class F> optional<T> or_else (F &&f) const &;
+    
+    template <class F, detail::disable_if_ret_void<F>*=nullptr>
+    constexpr optional<T> or_else(F&& f) &;
+    
+    template <class F> optional<T> or_else (F &&f) &&;
+    template <class F> optional<T> or_else (F &&f) const &&;
+    
+    template <class F, detail::disable_if_ret_void<F>*=nullptr>
+    constexpr optional<T> or_else(F&& f) &&;
+    
+    template <class F, detail::disable_if_ret_void<F>*=nullptr>
+    constexpr optional<T> or_else(F&& f) const &;
+    
+    template <class F, detail::disable_if_ret_void<F>*=nullptr>
+    optional<T> or_else(F&& f) const &&;
+    
+    template <class F, class U>
+    U map_or(F&& f, U&& u) &;
+    
+    template <class F, class U>
+    U map_or(F&& f, U&& u) &&;
+    
+    template <class F, class U>
+    U map_or(F&& f, U&& u) const &;
+    
+    template <class F, class U>
+    U map_or(F&& f, U&& u) const &&;
+    
+    template <class F, class U>
+    U map_or_else(F&& f, U&& u) &;
+    
+    template <class F, class U>
+    U map_or_else(F&& f, U&& u) &&;
+    
+    template <class F, class U>
+    U map_or_else(F&& f, U&& u) const &;
+    
+    template <class F, class U>
+    U map_or_else(F&& f, U&& u) const &&;
+};
+ +An optional object is an object that contains the storage for another object and manages the lifetime of this contained object, if any. The contained object may be initialized after the optional object has been initialized, and may be destroyed before the optional object has been destroyed. The initialization state of the contained object is tracked by the optional object. + +### Function template `tl::optional::and_then` + +
(1)  template <class F>
+     constexpr detail::invoke_result_t<F, T> and_then(F&& f) &;
+
+(2)  template <class F>
+     constexpr detail::invoke_result_t<F, T> and_then(F&& f) const &;
+ +Carries out some operation which returns an optional on the stored object if there is one. + +*Requires*: `std::invoke(std::forward(f), value())` returns a `std::optional` for some `U`. + +*Returns*: Let `U` be the result of `std::invoke(std::forward(f), value())`. Returns a `std::optional`. The return value is empty if `*this` is empty, otherwise the return value of `std::invoke(std::forward(f), value())` is returned. + +### Function template `tl::optional::and_then` + +
(1)  template <class F>
+     constexpr detail::invoke_result_t<F, T> and_then(F&& f) &&;
+
+(2)  template <class F>
+     constexpr detail::invoke_result_t<F, T> and_then(F&& f) const &&;
+ +Carries out some operation which returns an optional on the stored object if there is one. + +*Requires*: `std::invoke(std::forward(f), std::move(value()))` returns a `std::optional` for some `U`. + +*Returns*: Let `U` be the result of `std::invoke(std::forward(f), std::move(value()))`. Returns a `std::optional`. The return value is empty if `*this` is empty, otherwise the return value of `std::invoke(std::forward(f), std::move(value()))` is returned. + +### Function template `tl::optional::map` + +
(1)  template <class F> auto map(F &&f) &;
+
+(2)  template <class F> auto map(F &&f) const &;
+ +Carries out some operation on the stored object if there is one. + +*Returns*: Let `U` be the result of `std::invoke(std::forward(f), value())`. Returns a `std::optional`. The return value is empty if `*this` is empty, otherwise an `optional` is constructed from the return value of `std::invoke(std::forward(f), value())` and is returned. + +### Function template `tl::optional::map` + +
(1)  template <class F> auto map(F &&f) &;
+
+(2)  template <class F> auto map(F &&f) const &&;
+ +Carries out some operation on the stored object if there is one. + +*Returns*: Let `U` be the result of `std::invoke(std::forward(f), std::move(value()))`. Returns a `std::optional`. The return value is empty if `*this` is empty, otherwise an `optional` is constructed from the return value of `std::invoke(std::forward(f), std::move(value()))` and is returned. + +### Function template `tl::optional::or_else` + +
(1)  template <class F> optional<T> or_else (F &&f) &;
+
+(2)  template <class F> optional<T> or_else (F &&f) const &;
+ +Calls `f` if the optional is empty + +*Requires*: `std::invoke_result_t` must be void or convertible to `optional`. + +*Effects*: If `*this` has a value, returns `*this`. Otherwise, if `f` returns `void`, calls `std::forward(f)` and returns `std::nullopt`. Otherwise, returns `std::forward(f)()`. + +### Function template `tl::optional::or_else` + +
(1)  template <class F> optional<T> or_else (F &&f) &&;
+
+(2)  template <class F> optional<T> or_else (F &&f) const &&;
+ +Calls `f` if the optional is empty + +*Requires*: `std::invoke_result_t` must be void or convertible to `optional`. + +*Effects*: If `*this` has a value, returns `std::move(*this)`. Otherwise, if `f` returns `void`, calls `std::forward(f)` and returns `std::nullopt`. Otherwise, returns `std::forward(f)()`. + +----- + +-----