diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..4075734 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,407 @@ +# Header file `expected.hpp` + +
#define TL_EXPECTED_HPP
+
+#define TL_EXPECTED_GCC49
+
+#define TL_EXPECTED_NO_CONSTRR
+
+#define TL_EXPECTED_CXX14
+
+#define TL_IN_PLACE_MONOSTATE_DEFINED
+
+namespace tl
+{
+    class monostate;
+    
+    struct in_place_t;
+    
+    constexpr in_place_t{} in_place;
+    
+    template <class E>
+    class unexpected;
+    
+    template <class E>
+    constexpr bool operator==(const unexpected<E>& lhs, const unexpected<E>& rhs);
+    template <class E>
+    constexpr bool operator!=(const unexpected<E>& lhs, const unexpected<E>& rhs);
+    template <class E>
+    constexpr bool operator<(const unexpected<E>& lhs, const unexpected<E>& rhs);
+    template <class E>
+    constexpr bool operator<=(const unexpected<E>& lhs, const unexpected<E>& rhs);
+    template <class E>
+    constexpr bool operator>(const unexpected<E>& lhs, const unexpected<E>& rhs);
+    template <class E>
+    constexpr bool operator>=(const unexpected<E>& lhs, const unexpected<E>& rhs);
+    
+    template <class E>
+    unexpected<E> make_unexpected(E&& e);
+    
+    struct unexpect_t;
+    
+    constexpr unexpect_t{} unexpect;
+    
+    template <class E>
+    class bad_expected_access;
+    
+    template <class T, class E>
+    class expected;
+    
+    template <class T, class E, class U, class F>
+    constexpr bool operator==(const expected<T, E>& lhs, const expected<U, F>& rhs);
+    
+    template <class T, class E, class U, class F>
+    constexpr bool operator!=(const expected<T, E>& lhs, const expected<U, F>& rhs);
+    
+    template <class T, class E, class U, class F>
+    constexpr bool operator<(const expected<T, E>& lhs, const expected<U, F>& rhs);
+    
+    template <class T, class E, class U, class F>
+    constexpr bool operator>(const expected<T, E>& lhs, const expected<U, F>& rhs);
+    
+    template <class T, class E, class U, class F>
+    constexpr bool operator<=(const expected<T, E>& lhs, const expected<U, F>& rhs);
+    
+    template <class T, class E, class U, class F>
+    constexpr bool operator>=(const expected<T, E>& lhs, const expected<U, F>& rhs);
+    
+    template <class T, class E, class U>
+    constexpr bool operator==(const expected<T, E>& x, const U& v);
+    
+    template <class T, class E, class U>
+    constexpr bool operator==(const U& v, const expected<T, E>& x);
+    
+    template <class T, class E, class U>
+    constexpr bool operator!=(const expected<T, E>& x, const U& v);
+    
+    template <class T, class E, class U>
+    constexpr bool operator!=(const U& v, const expected<T, E>& x);
+    
+    template <class T, class E, class U>
+    constexpr bool operator<(const expected<T, E>& x, const U& v);
+    
+    template <class T, class E, class U>
+    constexpr bool operator<(const U& v, const expected<T, E>& x);
+    
+    template <class T, class E, class U>
+    constexpr bool operator<=(const expected<T, E>& x, const U& v);
+    
+    template <class T, class E, class U>
+    constexpr bool operator<=(const U& v, const expected<T, E>& x);
+    
+    template <class T, class E, class U>
+    constexpr bool operator>(const expected<T, E>& x, const U& v);
+    
+    template <class T, class E, class U>
+    constexpr bool operator>(const U& v, const expected<T, E>& x);
+    
+    template <class T, class E, class U>
+    constexpr bool operator>=(const expected<T, E>& x, const U& v);
+    
+    template <class T, class E, class U>
+    constexpr bool operator>=(const U& v, const expected<T, E>& x);
+    
+    template <class T, class E>
+    constexpr bool operator==(const expected<T, E>& x, const unexpected<E>& e);
+    
+    template <class T, class E>
+    constexpr bool operator==(const unexpected<E>& e, const expected<T, E>& x);
+    
+    template <class T, class E>
+    constexpr bool operator!=(const expected<T, E>& x, const unexpected<E>& e);
+    
+    template <class T, class E>
+    constexpr bool operator!=(const unexpected<E>& e, const expected<T, E>& x);
+    
+    template <class T, class E>
+    constexpr bool operator<(const expected<T, E>& x, const unexpected<E>& e);
+    
+    template <class T, class E>
+    constexpr bool operator<(const unexpected<E>& e, const expected<T, E>& x);
+    
+    template <class T, class E>
+    constexpr bool operator<=(const expected<T, E>& x, const unexpected<E>& e);
+    
+    template <class T, class E>
+    constexpr bool operator<=(const unexpected<E>& e, const expected<T, E>& x);
+    
+    template <class T, class E>
+    constexpr bool operator>(const expected<T, E>& x, const unexpected<E>& e);
+    
+    template <class T, class E>
+    constexpr bool operator>(const unexpected<E>& e, const expected<T, E>& x);
+    
+    template <class T, class E>
+    constexpr bool operator>=(const expected<T, E>& x, const unexpected<E>& e);
+    
+    template <class T, class E>
+    constexpr bool operator>=(const unexpected<E>& e, const expected<T, E>& x);
+    
+    template <class T, class E, 'hidden'>
+    void swap(expected<T, E>& lhs, expected<T, E>& rhs) noexcept(noexcept(lhs.swap(rhs)));
+}
+ +## Class `tl::monostate` + +
class monostate
+{
+};
+ +Used to represent an expected with no data + +## Struct `tl::in_place_t` + +
struct in_place_t
+{
+    in_place_t() = default;
+};
+ +A tag type to tell expected to construct its value in-place + +## Variable `tl::in_place` + +
constexpr in_place_t{} in_place;
+ +A tag to tell expected to construct its value in-place + +## Class template `tl::unexpected` + +
template <class E>
+class unexpected
+{
+public:
+    unexpected() = delete;
+    
+    constexpr unexpected(const E& e);
+    
+    constexpr unexpected(E&& e);
+    
+    constexpr const E& value() const &;
+    constexpr E& value() &;
+    constexpr E&& value() &&;
+};
+ +Used as a wrapper to store the unexpected value + +### Function `tl::unexpected::value` + +
(1)  constexpr const E& value() const &;
+
+(2)  constexpr E& value() &;
+
+(3)  constexpr E&& value() &&;
+ +*Returns*: the contained value + +----- + +## Comparison operator `tl::operator==` + +
(1)  template <class E>
+     constexpr bool operator==(const unexpected<E>& lhs, const unexpected<E>& rhs);
+
+(2)  template <class E>
+     constexpr bool operator!=(const unexpected<E>& lhs, const unexpected<E>& rhs);
+
+(3)  template <class E>
+     constexpr bool operator<(const unexpected<E>& lhs, const unexpected<E>& rhs);
+
+(4)  template <class E>
+     constexpr bool operator<=(const unexpected<E>& lhs, const unexpected<E>& rhs);
+
+(5)  template <class E>
+     constexpr bool operator>(const unexpected<E>& lhs, const unexpected<E>& rhs);
+
+(6)  template <class E>
+     constexpr bool operator>=(const unexpected<E>& lhs, const unexpected<E>& rhs);
+ +Compares two unexpected objects + +Simply compares lhs.value() to rhs.value() + +## Function template `tl::make_unexpected` + +
template <class E>
+unexpected<E> make_unexpected(E&& e);
+ +Create an `unexpected` from `e`, deducing the return type + +*Example:* auto e1 = tl::make\_unexpected(42); unexpected\ e2 (42); //same semantics + +## Struct `tl::unexpect_t` + +
struct unexpect_t
+{
+    unexpect_t() = default;
+};
+ +A tag type to tell expected to construct the unexpected value + +## Variable `tl::unexpect` + +
constexpr unexpect_t{} unexpect;
+ +A tag to tell expected to construct the unexpected value + +## Class template `tl::expected` + +
template <class T, class E>
+class expected
+{
+public:
+    using value_type = T;
+    
+    using error_type = E;
+    
+    using unexpected_type = unexpected<E>;
+    
+    template <class F>
+    'hidden' and_then(F&& f) &;
+    template <class F>
+    constexpr auto and_then(F &&f) &&;
+    template <class F>
+    constexpr auto and_then(F &&f) const &;
+    
+    template <class F> constexpr auto map(F &&f) &;
+    template <class F> constexpr auto map(F &&f) &&;
+    template <class F> constexpr auto map(F &&f) const &;
+    
+    template <class F> constexpr auto map_error(F &&f) &;
+    template <class F> constexpr auto map_error(F &&f) &&;
+    template <class F> constexpr auto map_error(F &&f) const &;
+    
+    constexpr expected() = default;
+    
+    constexpr expected(const expected& rhs) = default;
+    
+    constexpr expected(expected&& rhs) = default;
+    
+    constexpr expected& operator=(const expected& rhs) = default;
+    
+    constexpr expected& operator=(expected&& rhs) = default;
+    
+    template <class ... Args, 'hidden' ... = nullptr>
+    constexpr expected(in_place_t, Args&&... args);
+    
+    template <class U, class ... Args, 'hidden' ... = nullptr>
+    constexpr expected(in_place_t, std::initializer_list<U> il, Args&&... args);
+    
+    EXPLICIT constexpr expected(const unexpected<G> &e);
+    EXPLICIT constexpr expected(unexpected<G> &&e);
+    
+    template <class ... Args, 'hidden' ... = nullptr>
+    constexpr expected(unexpect_t, Args&&... args);
+    
+    template <class U, class G, 'hidden'>
+    constexpr expected(const expected<U, G>& rhs);
+    
+    template <class U, class G, 'hidden'>
+    constexpr expected(expected<U, G>&& rhs);
+    
+    template <class U = T, 'hidden'>
+    constexpr expected(U&& v);
+    
+    template <class U = T, 'hidden', 'hidden'>
+    expected& operator=(U&& v);
+    
+    template <class G = E, 'hidden'>
+    expected& operator=(const unexpected<G>& rhs);
+    
+    template <class G = E, 'hidden'>
+    expected& operator=(unexpected<G>&& rhs) noexcept;
+    
+    template <class ... Args, 'hidden' ... = nullptr>
+    void emplace(Args&&... args);
+    
+    template <class U, class ... Args, 'hidden' ... = nullptr>
+    void emplace(std::initializer_list<U> il, Args&&... args);
+    
+    void swap(expected& rhs) noexcept(std::is_nothrow_move_constructible<T>::value&&noexcept(swap(std::declval<T&>(), std::declval<T&>()))&&std::is_nothrow_move_constructible<E>::value&&noexcept(swap(std::declval<E&>(), std::declval<E&>())));
+    
+    constexpr const T* operator->() const;
+    
+    constexpr T* operator->();
+    
+    constexpr const T& operator*() const &;
+    
+    constexpr T& operator*() &;
+    
+    constexpr const T&& operator*() const &&;
+    
+    constexpr T&& operator*() &&;
+    
+    constexpr operator bool() const noexcept;
+    
+    constexpr bool has_value() const noexcept;
+    
+    constexpr const T& value() const &;
+    
+    constexpr T& value() &;
+    
+    constexpr const T&& value() const &&;
+    
+    constexpr T&& value() &&;
+    
+    constexpr const E& error() const &;
+    
+    constexpr E& error() &;
+    
+    constexpr const E&& error() const &&;
+    
+    constexpr E&& error() &&;
+    
+    template <class U>
+    constexpr T value_or(U&& v) const &;
+    
+    template <class U>
+    T value_or(U&& v) &&;
+};
+ +An `expected` object is an object that contains the storage for another object and manages the lifetime of this contained object `T`. Alternatively it could contain the storage for another unexpected object `E`. The contained object may not be initialized after the expected object has been initialized, and may not be destroyed before the expected object has been destroyed. The initialization state of the contained object is tracked by the expected object. + +### Function template `tl::expected::and_then` + +
(1)  template <class F>
+     'hidden' and_then(F&& f) &;
+
+(2)  template <class F>
+     constexpr auto and_then(F &&f) &&;
+
+(3)  template <class F>
+     constexpr auto 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. \\group and\_then \\synopsis template \\\nconstexpr auto and\_then(F &\&f) &; + +### Function template `tl::expected::map` + +
(1)  template <class F> constexpr auto map(F &&f) &;
+
+(2)  template <class F> constexpr auto map(F &&f) &&;
+
+(3)  template <class F> constexpr 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::expected`. If `*this` is unexpected, the result is `*this`, otherwise an `expected` is constructed from the return value of `std::invoke(std::forward(f), value())` and is returned. + +### Function template `tl::expected::map_error` + +
(1)  template <class F> constexpr auto map_error(F &&f) &;
+
+(2)  template <class F> constexpr auto map_error(F &&f) &&;
+
+(3)  template <class F> constexpr auto map_error(F &&f) const &;
+ +Carries out some operation on the stored unexpected object if there is one. + +*Returns*: Let `U` be the result of `std::invoke(std::forward(f), value())`. Returns a `std::expected`. If `*this` has an expected value, the result is `*this`, otherwise an `expected` is constructed from `make_unexpected(std::invoke(std::forward(f), value()))` and is returned. + +### Function template `tl::expected::expected` + +
(1)  EXPLICIT constexpr expected(const unexpected<G> &e);
+
+(2)  EXPLICIT constexpr expected(unexpected<G> &&e);
+ +----- + +----- diff --git a/expected.hpp b/expected.hpp index 57b7827..d212a12 100644 --- a/expected.hpp +++ b/expected.hpp @@ -139,8 +139,8 @@ public: constexpr E &value() & { return m_val; } /// \group unexpected_value constexpr E &&value() && { return std::move(m_val); } - /// \group unexpected_value - constexpr E const &&value() const && { return std::move(m_val); } + /// \exclude + constexpr const E &&value() const && { return std::move(m_val); } private: E m_val; @@ -374,7 +374,8 @@ template struct expected_storage_base { // expected_copy_move_base is used to conditionally delete the move/copy // constructors/assignment operators depending on the traits of T and E. - // TODO these could be reduced a bit by splitting construction and assignment into different bases +// TODO these could be reduced a bit by splitting construction and assignment +// into different bases template < class T, class E, bool EnableCopy = (std::is_copy_constructible::value && @@ -869,8 +870,7 @@ public: "F must return an expected"); return has_value() ? detail::invoke(std::forward(f), std::move(**this)) - : result(unexpect, std:: - : move(this->error())); + : result(unexpect, std::move(this->error())); } #endif @@ -937,32 +937,44 @@ public: !defined(TL_EXPECTED_GCC54) /// \brief 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::expected`. The return value is empty if - /// `*this` is empty, otherwise an `expected` is constructed from the + /// value())`. Returns a `std::expected`. If `*this` is unexpected, the + /// result is `*this`, otherwise an `expected` is constructed from the /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. \group map \synopsis template auto map(F &&f) &; + /// returned. + /// + /// \group map + /// \synopsis template constexpr auto map(F &&f) &; template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & { return map_impl(*this, std::forward(f)); } + /// \group map + /// \synopsis template constexpr auto map(F &&f) &&; template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && { return map_impl(std::move(*this), std::forward(f)); } + /// \group map + /// \synopsis template constexpr auto map(F &&f) const &; template constexpr auto map(F &&f) const & { return map_impl(*this, std::forward(f)); } + /// \group map + /// \synopsis template constexpr auto map(F &&f) const &&; template constexpr auto map(F &&f) const && { return map_impl(std::move(*this), std::forward(f)); } #else /// \brief 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::expected`. The return value is empty if - /// `*this` is empty, otherwise an `expected` is constructed from the + /// value())`. Returns a `std::expected`. If `*this` is unexpected, the + /// result is `*this`, otherwise an `expected` is constructed from the /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. \group map \synopsis template auto map(F &&f) &; + /// returned. + /// + /// \group map + /// \synopsis template constexpr auto map(F &&f) &; template TL_EXPECTED_11_CONSTEXPR decltype(map_impl(std::declval(), std::declval())) @@ -970,13 +982,17 @@ public: return map_impl(*this, std::forward(f)); } + /// \group map + /// \synopsis template constexpr auto map(F &&f) &&; template - TL_EXPECTED_11_CONSTEXPR decltype(map_impl(std::declval(), + TL_EXPECTED_11_CONSTEXPR decltype(map_impl(std::declval(), std::declval())) map(F &&f) && { return map_impl(std::move(*this), std::forward(f)); } + /// \group map + /// \synopsis template constexpr auto map(F &&f) const &; template constexpr decltype(map_impl(std::declval(), std::declval())) @@ -985,6 +1001,8 @@ public: } #ifndef TL_EXPECTED_NO_CONSTRR + /// \group map + /// \synopsis template constexpr auto map(F &&f) const &&; template constexpr decltype(map_impl(std::declval(), std::declval())) @@ -996,36 +1014,48 @@ public: #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) - /// \brief Carries out some operation on the stored object if there is one. + /// \brief Carries out some operation on the stored unexpected object if there + /// is one. /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::expected`. The return value is empty if - /// `*this` is empty, otherwise an `expected` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. \group map_error \synopsis template auto map_error(F - /// &&f) &; + /// value())`. Returns a `std::expected`. If `*this` has an expected + /// value, the result is `*this`, otherwise an `expected` is constructed + /// from `make_unexpected(std::invoke(std::forward(f), value()))` and is + /// returned. + /// + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) &; template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & { return map_error_impl(*this, std::forward(f)); } + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) &&; template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && { return map_error_impl(std::move(*this), std::forward(f)); } + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) const &; template constexpr auto map_error(F &&f) const & { return map_error_impl(*this, std::forward(f)); } + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) const &&; template constexpr auto map_error(F &&f) const && { return map_error_impl(std::move(*this), std::forward(f)); } #else - /// \brief Carries out some operation on the stored object if there is one. + /// \brief Carries out some operation on the stored unexpected object if there + /// is one. /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::expected`. The return value is empty if - /// `*this` is empty, otherwise an `expected` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. \group map_error \synopsis template auto map_error(F - /// &&f) &; + /// value())`. Returns a `std::expected`. If `*this` has an expected + /// value, the result is `*this`, otherwise an `expected` is constructed + /// from `make_unexpected(std::invoke(std::forward(f), value()))` and is + /// returned. + /// + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) &; template TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), std::declval())) @@ -1033,6 +1063,8 @@ public: return map_error_impl(*this, std::forward(f)); } + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) &&; template TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), std::declval())) @@ -1040,6 +1072,8 @@ public: return map_error_impl(std::move(*this), std::forward(f)); } + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) const &; template constexpr decltype(map_error_impl(std::declval(), std::declval())) @@ -1048,6 +1082,8 @@ public: } #ifndef TL_EXPECTED_NO_CONSTRR + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) const &&; template constexpr decltype(map_error_impl(std::declval(), std::declval())) @@ -1077,15 +1113,18 @@ public: : impl_base(in_place, il, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} + /// \group unexpected_ctor + /// \synopsis EXPLICIT constexpr expected(const unexpected &e); template ::value> * = nullptr, detail::enable_if_t::value> * = nullptr> - explicit constexpr expected(unexpected const &e) + explicit constexpr expected(const unexpected &e) : impl_base(unexpect, e.value()), ctor_base(detail::default_constructor_tag{}) {} + /// \exclude template < class G = E, detail::enable_if_t::value> * = @@ -1095,6 +1134,8 @@ public: : impl_base(unexpect, e.value()), ctor_base(detail::default_constructor_tag{}) {} + /// \group unexpected_ctor + /// \synopsis EXPLICIT constexpr expected(unexpected &&e); template < class G = E, detail::enable_if_t::value> * = nullptr, @@ -1104,6 +1145,7 @@ public: : impl_base(unexpect, std::move(e.value())), ctor_base(detail::default_constructor_tag{}) {} + /// \exclude template < class G = E, detail::enable_if_t::value> * = nullptr, @@ -1120,6 +1162,7 @@ public: : impl_base(unexpect, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} + /// \exclude template &, Args &&...>::value> * = nullptr> @@ -1130,8 +1173,8 @@ public: // TODO SFINAE template ::value || - !std::is_convertible::value)> * = + detail::enable_if_t::value && + std::is_convertible::value)> * = nullptr> explicit constexpr expected(const expected &rhs) : ctor_base(detail::default_constructor_tag{}) { @@ -1143,11 +1186,12 @@ public: } // TODO SFINAE - template < - class U, class G, - detail::enable_if_t<(!std::is_convertible::value || - !std::is_convertible::value)> * = nullptr> - explicit constexpr expected(const expected &rhs) + /// \exclude + template ::value && + std::is_convertible::value)> * = + nullptr> + constexpr expected(const expected &rhs) : ctor_base(detail::default_constructor_tag{}) { if (rhs.has_value()) { ::new (valptr()) T(*rhs); @@ -1159,7 +1203,22 @@ public: // TODO SFINAE template < class U, class G, - detail::enable_if_t<(std::is_convertible::value || + detail::enable_if_t::value && + std::is_convertible::value)> * = nullptr> + explicit constexpr expected(expected &&rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + ::new (valptr()) T(std::move(*rhs)); + } else { + ::new (errptr()) unexpected_type(unexpected(std::move(rhs.error()))); + } + } + + // TODO SFINAE + /// \exclude + template < + class U, class G, + detail::enable_if_t<(std::is_convertible::value && std::is_convertible::value)> * = nullptr> constexpr expected(expected &&rhs) : ctor_base(detail::default_constructor_tag{}) { @@ -1176,6 +1235,7 @@ public: explicit constexpr expected(U &&v) : expected(in_place, std::forward(v)) {} // TODO SFINAE + /// \exclude template ::value> * = nullptr> constexpr expected(U &&v) : expected(in_place, std::forward(v)) {} @@ -1203,6 +1263,7 @@ public: return *this; } + /// \exclude template < class U = T, detail::enable_if_t< @@ -1274,6 +1335,7 @@ public: } } + /// \exclude template ::value> * = nullptr> void emplace(Args &&... args) { @@ -1307,6 +1369,7 @@ public: } } + /// \exclude template &, Args &&...>::value> * = nullptr> @@ -1397,10 +1460,9 @@ public: "T must be move-constructible and convertible to from U&&"); return bool(*this) ? std::move(**this) : static_cast(std::forward(v)); } - -private: }; +/// \exclude namespace detail { template using err_t = typename detail::decay_t::error_type; template using ret_t = expected>;