From c78e903273c13c0d3022e381f69e734ec1d36613 Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Mon, 21 Aug 2023 13:03:39 -0400 Subject: [PATCH] chore: update `expected` to latest version --- include/ada/expected.h | 454 +++++++++++++++++++++-------------------- 1 file changed, 234 insertions(+), 220 deletions(-) diff --git a/include/ada/expected.h b/include/ada/expected.h index 51bbe9150..291da8c05 100644 --- a/include/ada/expected.h +++ b/include/ada/expected.h @@ -22,8 +22,8 @@ #define TL_EXPECTED_HPP #define TL_EXPECTED_VERSION_MAJOR 1 -#define TL_EXPECTED_VERSION_MINOR 0 -#define TL_EXPECTED_VERSION_PATCH 1 +#define TL_EXPECTED_VERSION_MINOR 1 +#define TL_EXPECTED_VERSION_PATCH 0 #include #include @@ -41,34 +41,44 @@ #define TL_EXPECTED_MSVC2015_CONSTEXPR constexpr #endif -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ !defined(__clang__)) #define TL_EXPECTED_GCC49 #endif -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \ +#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \ !defined(__clang__)) #define TL_EXPECTED_GCC54 #endif -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \ +#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \ !defined(__clang__)) #define TL_EXPECTED_GCC55 #endif -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ +#if !defined(TL_ASSERT) +//can't have assert in constexpr in C++11 and GCC 4.9 has a compiler bug +#if (__cplusplus > 201103L) && !defined(TL_EXPECTED_GCC49) +#include +#define TL_ASSERT(x) assert(x) +#else +#define TL_ASSERT(x) +#endif +#endif + +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ !defined(__clang__)) // GCC < 5 doesn't support overloading on const&& for member functions #define TL_EXPECTED_NO_CONSTRR // GCC < 5 doesn't support some standard C++11 type traits -#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ +#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ std::has_trivial_copy_constructor -#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ +#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ std::has_trivial_copy_assign // This one will be different for GCC 5.7 if it's ever supported -#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ +#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ std::is_trivially_destructible // GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks @@ -85,22 +95,22 @@ struct is_trivially_copy_constructible template struct is_trivially_copy_constructible> : std::false_type {}; #endif -} // namespace detail -} // namespace tl +} // namespace detail +} // namespace tl #endif -#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ +#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ tl::detail::is_trivially_copy_constructible -#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ +#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ std::is_trivially_copy_assignable -#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ +#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ std::is_trivially_destructible #else -#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ +#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ std::is_trivially_copy_constructible -#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ +#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \ std::is_trivially_copy_assignable -#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ +#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ std::is_trivially_destructible #endif @@ -114,7 +124,7 @@ struct is_trivially_copy_constructible> : std::false_type {}; #define TL_EXPECTED_GCC49_CONSTEXPR constexpr #endif -#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || \ +#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || \ defined(TL_EXPECTED_GCC49)) #define TL_EXPECTED_11_CONSTEXPR #else @@ -122,8 +132,7 @@ struct is_trivially_copy_constructible> : std::false_type {}; #endif namespace tl { -template -class expected; +template class expected; #ifndef TL_MONOSTATE_INPLACE_MUTEX #define TL_MONOSTATE_INPLACE_MUTEX @@ -135,9 +144,8 @@ struct in_place_t { static constexpr in_place_t in_place{}; #endif -template -class unexpected { - public: +template class unexpected { +public: static_assert(!std::is_same::value, "E must not be void"); unexpected() = delete; @@ -161,13 +169,12 @@ class unexpected { TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); } constexpr const E &&value() const && { return std::move(m_val); } - private: +private: E m_val; }; #ifdef __cpp_deduction_guides -template -unexpected(E) -> unexpected; +template unexpected(E) -> unexpected; #endif template @@ -211,6 +218,7 @@ template #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED throw std::forward(e); #else + (void)e; #ifdef _MSC_VER __assume(0); #else @@ -222,22 +230,18 @@ template #ifndef TL_TRAITS_MUTEX #define TL_TRAITS_MUTEX // C++14-style aliases for brevity -template -using remove_const_t = typename std::remove_const::type; +template using remove_const_t = typename std::remove_const::type; template using remove_reference_t = typename std::remove_reference::type; -template -using decay_t = typename std::decay::type; +template using decay_t = typename std::decay::type; template using enable_if_t = typename std::enable_if::type; template using conditional_t = typename std::conditional::type; // std::conjunction from C++17 -template -struct conjunction : std::true_type {}; -template -struct conjunction : B {}; +template struct conjunction : std::true_type {}; +template struct conjunction : B {}; template struct conjunction : std::conditional, B>::type {}; @@ -271,12 +275,9 @@ template struct is_pointer_to_non_const_member_func : std::true_type {}; -template -struct is_const_or_const_ref : std::false_type {}; -template -struct is_const_or_const_ref : std::true_type {}; -template -struct is_const_or_const_ref : std::true_type {}; +template struct is_const_or_const_ref : std::false_type {}; +template struct is_const_or_const_ref : std::true_type {}; +template struct is_const_or_const_ref : std::true_type {}; #endif // std::invoke from C++17 @@ -303,8 +304,7 @@ constexpr auto invoke(Fn &&f, Args &&...args) noexcept( } // std::invoke_result from C++17 -template -struct invoke_result_impl; +template struct invoke_result_impl; template struct invoke_result_impl< @@ -323,11 +323,9 @@ using invoke_result_t = typename invoke_result::type; #if defined(_MSC_VER) && _MSC_VER <= 1900 // TODO make a version which works with MSVC 2015 -template -struct is_swappable : std::true_type {}; +template struct is_swappable : std::true_type {}; -template -struct is_nothrow_swappable : std::true_type {}; +template struct is_nothrow_swappable : std::true_type {}; #else // https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept namespace swap_adl_tests { @@ -335,22 +333,18 @@ namespace swap_adl_tests { // signature) struct tag {}; -template -tag swap(T &, T &); -template -tag swap(T (&a)[N], T (&b)[N]); +template tag swap(T &, T &); +template tag swap(T (&a)[N], T (&b)[N]); // helper functions to test if an unqualified swap is possible, and if it // becomes std::swap -template -std::false_type can_swap(...) noexcept(false); +template std::false_type can_swap(...) noexcept(false); template (), std::declval()))> std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), std::declval()))); -template -std::false_type uses_std(...); +template std::false_type uses_std(...); template std::is_same(), std::declval())), tag> uses_std(int); @@ -367,7 +361,7 @@ struct is_std_swap_noexcept : is_std_swap_noexcept {}; template struct is_adl_swap_noexcept : std::integral_constant(0))> {}; -} // namespace swap_adl_tests +} // namespace swap_adl_tests template struct is_swappable @@ -400,12 +394,10 @@ struct is_nothrow_swappable #endif // Trait for checking if a type is a tl::expected -template -struct is_expected_impl : std::false_type {}; +template struct is_expected_impl : std::false_type {}; template struct is_expected_impl> : std::true_type {}; -template -using is_expected = is_expected_impl>; +template using is_expected = is_expected_impl>; template using expected_enable_forward_value = detail::enable_if_t< @@ -444,7 +436,7 @@ using is_copy_assignable_or_void = is_void_or>; template using is_move_assignable_or_void = is_void_or>; -} // namespace detail +} // namespace detail namespace detail { struct no_init_t {}; @@ -505,8 +497,7 @@ struct expected_storage_base { // This specialization is for when both `T` and `E` are trivially-destructible, // so the destructor of the `expected` can be trivial. -template -struct expected_storage_base { +template struct expected_storage_base { constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} @@ -546,8 +537,7 @@ struct expected_storage_base { }; // T is trivial, E is not. -template -struct expected_storage_base { +template struct expected_storage_base { constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} @@ -593,8 +583,7 @@ struct expected_storage_base { }; // E is trivial, T is not. -template -struct expected_storage_base { +template struct expected_storage_base { constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} @@ -638,13 +627,12 @@ struct expected_storage_base { }; // `T` is `void`, `E` is trivially-destructible -template -struct expected_storage_base { -#if __GNUC__ <= 5 -// no constexpr for GCC 4/5 bug -#else +template struct expected_storage_base { + #if __GNUC__ <= 5 + //no constexpr for GCC 4/5 bug + #else TL_EXPECTED_MSVC2015_CONSTEXPR -#endif + #endif expected_storage_base() : m_has_val(true) {} constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {} @@ -675,8 +663,7 @@ struct expected_storage_base { }; // `T` is `void`, `E` is not trivially-destructible -template -struct expected_storage_base { +template struct expected_storage_base { constexpr expected_storage_base() : m_dummy(), m_has_val(true) {} constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {} @@ -715,20 +702,17 @@ template struct expected_operations_base : expected_storage_base { using expected_storage_base::expected_storage_base; - template - void construct(Args &&...args) noexcept { + template void construct(Args &&...args) noexcept { new (std::addressof(this->m_val)) T(std::forward(args)...); this->m_has_val = true; } - template - void construct_with(Rhs &&rhs) noexcept { + template void construct_with(Rhs &&rhs) noexcept { new (std::addressof(this->m_val)) T(std::forward(rhs).get()); this->m_has_val = true; } - template - void construct_error(Args &&...args) noexcept { + template void construct_error(Args &&...args) noexcept { new (std::addressof(this->m_unexpect)) unexpected(std::forward(args)...); this->m_has_val = false; @@ -851,15 +835,14 @@ struct expected_operations_base : expected_storage_base { geterr().~unexpected(); construct(std::move(rhs).get()); } else { - assign_common(rhs); + assign_common(std::move(rhs)); } } #endif // The common part of move/copy assigning - template - void assign_common(Rhs &&rhs) { + template void assign_common(Rhs &&rhs) { if (this->m_has_val) { if (rhs.m_has_val) { get() = std::forward(rhs).get(); @@ -905,27 +888,21 @@ template struct expected_operations_base : expected_storage_base { using expected_storage_base::expected_storage_base; - template - void construct() noexcept { - this->m_has_val = true; - } + template void construct() noexcept { this->m_has_val = true; } // This function doesn't use its argument, but needs it so that code in // levels above this can work independently of whether T is void - template - void construct_with(Rhs &&) noexcept { + template void construct_with(Rhs &&) noexcept { this->m_has_val = true; } - template - void construct_error(Args &&...args) noexcept { + template void construct_error(Args &&...args) noexcept { new (std::addressof(this->m_unexpect)) unexpected(std::forward(args)...); this->m_has_val = false; } - template - void assign(Rhs &&rhs) noexcept { + template void assign(Rhs &&rhs) noexcept { if (!this->m_has_val) { if (rhs.m_has_val) { geterr().~unexpected(); @@ -1002,8 +979,7 @@ struct expected_move_base : expected_copy_base { using expected_copy_base::expected_copy_base; }; #else -template -struct expected_move_base; +template struct expected_move_base; #endif template struct expected_move_base : expected_copy_base { @@ -1050,8 +1026,8 @@ struct expected_copy_assign_base : expected_move_base { this->assign(rhs); return *this; } - expected_copy_assign_base &operator=(expected_copy_assign_base &&rhs) = - default; + expected_copy_assign_base & + operator=(expected_copy_assign_base &&rhs) = default; }; // This class manages conditionally having a trivial move assignment operator @@ -1072,8 +1048,7 @@ struct expected_move_assign_base : expected_copy_assign_base { using expected_copy_assign_base::expected_copy_assign_base; }; #else -template -struct expected_move_assign_base; +template struct expected_move_assign_base; #endif template @@ -1086,8 +1061,8 @@ struct expected_move_assign_base expected_move_assign_base(expected_move_assign_base &&rhs) = default; - expected_move_assign_base &operator=(const expected_move_assign_base &rhs) = - default; + expected_move_assign_base & + operator=(const expected_move_assign_base &rhs) = default; expected_move_assign_base & operator=(expected_move_assign_base &&rhs) noexcept( @@ -1109,10 +1084,10 @@ struct expected_delete_ctor_base { expected_delete_ctor_base() = default; expected_delete_ctor_base(const expected_delete_ctor_base &) = default; expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = - default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = - default; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; }; template @@ -1120,10 +1095,10 @@ struct expected_delete_ctor_base { expected_delete_ctor_base() = default; expected_delete_ctor_base(const expected_delete_ctor_base &) = default; expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = - default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = - default; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; }; template @@ -1131,10 +1106,10 @@ struct expected_delete_ctor_base { expected_delete_ctor_base() = default; expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = - default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = - default; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; }; template @@ -1142,10 +1117,10 @@ struct expected_delete_ctor_base { expected_delete_ctor_base() = default; expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = - default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = - default; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; }; // expected_delete_assign_base will conditionally delete copy and move @@ -1165,10 +1140,10 @@ struct expected_delete_assign_base { expected_delete_assign_base(const expected_delete_assign_base &) = default; expected_delete_assign_base(expected_delete_assign_base &&) noexcept = default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = - default; - expected_delete_assign_base &operator=( - expected_delete_assign_base &&) noexcept = default; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = default; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = default; }; template @@ -1177,10 +1152,10 @@ struct expected_delete_assign_base { expected_delete_assign_base(const expected_delete_assign_base &) = default; expected_delete_assign_base(expected_delete_assign_base &&) noexcept = default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = - default; - expected_delete_assign_base &operator=( - expected_delete_assign_base &&) noexcept = delete; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = default; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = delete; }; template @@ -1189,10 +1164,10 @@ struct expected_delete_assign_base { expected_delete_assign_base(const expected_delete_assign_base &) = default; expected_delete_assign_base(expected_delete_assign_base &&) noexcept = default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = - delete; - expected_delete_assign_base &operator=( - expected_delete_assign_base &&) noexcept = default; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = delete; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = default; }; template @@ -1201,10 +1176,10 @@ struct expected_delete_assign_base { expected_delete_assign_base(const expected_delete_assign_base &) = default; expected_delete_assign_base(expected_delete_assign_base &&) noexcept = default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = - delete; - expected_delete_assign_base &operator=( - expected_delete_assign_base &&) noexcept = delete; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = delete; + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = delete; }; // This is needed to be able to construct the expected_default_ctor_base which @@ -1214,7 +1189,7 @@ struct default_constructor_tag { }; // expected_default_ctor_base will ensure that expected has a deleted default -// constructor if T is not default constructible. +// consturctor if T is not default constructible. // This specialization is for when T is default constructible template -struct expected_default_ctor_base { +template struct expected_default_ctor_base { constexpr expected_default_ctor_base() noexcept = delete; constexpr expected_default_ctor_base( expected_default_ctor_base const &) noexcept = default; constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = default; - expected_default_ctor_base &operator=( - expected_default_ctor_base const &) noexcept = default; - expected_default_ctor_base &operator=( - expected_default_ctor_base &&) noexcept = default; + expected_default_ctor_base & + operator=(expected_default_ctor_base const &) noexcept = default; + expected_default_ctor_base & + operator=(expected_default_ctor_base &&) noexcept = default; constexpr explicit expected_default_ctor_base(default_constructor_tag) {} }; -} // namespace detail +} // namespace detail -template -class bad_expected_access : public std::exception { - public: +template class bad_expected_access : public std::exception { +public: explicit bad_expected_access(E e) : m_val(std::move(e)) {} virtual const char *what() const noexcept override { @@ -1264,7 +1237,7 @@ class bad_expected_access : public std::exception { const E &&error() const && { return std::move(m_val); } E &&error() && { return std::move(m_val); } - private: +private: E m_val; }; @@ -1314,42 +1287,40 @@ class expected : private detail::expected_move_assign_base, using impl_base = detail::expected_move_assign_base; using ctor_base = detail::expected_default_ctor_base; - public: +public: typedef T value_type; typedef E error_type; typedef unexpected unexpected_type; -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & { + template TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & { return and_then_impl(*this, std::forward(f)); } - template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && { + template TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && { return and_then_impl(std::move(*this), std::forward(f)); } - template - constexpr auto and_then(F &&f) const & { + template constexpr auto and_then(F &&f) const & { return and_then_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR - template - constexpr auto and_then(F &&f) const && { + template constexpr auto and_then(F &&f) const && { return and_then_impl(std::move(*this), std::forward(f)); } #endif #else template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & -> decltype(and_then_impl( - std::declval(), std::forward(f))) { + TL_EXPECTED_11_CONSTEXPR auto + and_then(F &&f) & -> decltype(and_then_impl(std::declval(), + std::forward(f))) { return and_then_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype(and_then_impl( - std::declval(), std::forward(f))) { + TL_EXPECTED_11_CONSTEXPR auto + and_then(F &&f) && -> decltype(and_then_impl(std::declval(), + std::forward(f))) { return and_then_impl(std::move(*this), std::forward(f)); } template @@ -1367,22 +1338,18 @@ class expected : private detail::expected_move_assign_base, #endif #endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - template - TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & { + template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & { return expected_map_impl(*this, std::forward(f)); } - template - TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && { + template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && { return expected_map_impl(std::move(*this), std::forward(f)); } - template - constexpr auto map(F &&f) const & { + template constexpr auto map(F &&f) const & { return expected_map_impl(*this, std::forward(f)); } - template - constexpr auto map(F &&f) const && { + template constexpr auto map(F &&f) const && { return expected_map_impl(std::move(*this), std::forward(f)); } #else @@ -1415,22 +1382,18 @@ class expected : private detail::expected_move_assign_base, #endif #endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - template - TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & { + template TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & { return expected_map_impl(*this, std::forward(f)); } - template - TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && { + template TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && { return expected_map_impl(std::move(*this), std::forward(f)); } - template - constexpr auto transform(F &&f) const & { + template constexpr auto transform(F &&f) const & { return expected_map_impl(*this, std::forward(f)); } - template - constexpr auto transform(F &&f) const && { + template constexpr auto transform(F &&f) const && { return expected_map_impl(std::move(*this), std::forward(f)); } #else @@ -1463,22 +1426,18 @@ class expected : private detail::expected_move_assign_base, #endif #endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - template - TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & { + template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & { return map_error_impl(*this, std::forward(f)); } - template - TL_EXPECTED_11_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)); } - template - constexpr auto map_error(F &&f) const & { + template constexpr auto map_error(F &&f) const & { return map_error_impl(*this, std::forward(f)); } - 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 @@ -1510,24 +1469,63 @@ class expected : private detail::expected_move_assign_base, } #endif #endif +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) + template TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + template TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + template constexpr auto transform_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + template constexpr auto transform_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#else template - expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & { - return or_else_impl(*this, std::forward(f)); + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); } +#ifndef TL_EXPECTED_NO_CONSTRR template - expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && { + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#endif +#endif + template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & { + return or_else_impl(*this, std::forward(f)); + } + + template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && { return or_else_impl(std::move(*this), std::forward(f)); } - template - expected constexpr or_else(F &&f) const & { + template expected constexpr or_else(F &&f) const & { return or_else_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR - template - expected constexpr or_else(F &&f) const && { + template expected constexpr or_else(F &&f) const && { return or_else_impl(std::move(*this), std::forward(f)); } #endif @@ -1841,7 +1839,7 @@ class expected : private detail::expected_move_assign_base, } } - private: +private: using t_is_void = std::true_type; using t_is_not_void = std::false_type; using t_is_nothrow_move_constructible = std::true_type; @@ -1928,7 +1926,7 @@ class expected : private detail::expected_move_assign_base, #endif } - public: +public: template detail::enable_if_t::value && detail::is_swappable::value && @@ -1951,27 +1949,37 @@ class expected : private detail::expected_move_assign_base, } } - constexpr const T *operator->() const { return valptr(); } - TL_EXPECTED_11_CONSTEXPR T *operator->() { return valptr(); } + constexpr const T *operator->() const { + TL_ASSERT(has_value()); + return valptr(); + } + TL_EXPECTED_11_CONSTEXPR T *operator->() { + TL_ASSERT(has_value()); + return valptr(); + } template ::value> * = nullptr> constexpr const U &operator*() const & { + TL_ASSERT(has_value()); return val(); } template ::value> * = nullptr> TL_EXPECTED_11_CONSTEXPR U &operator*() & { + TL_ASSERT(has_value()); return val(); } template ::value> * = nullptr> constexpr const U &&operator*() const && { + TL_ASSERT(has_value()); return std::move(val()); } template ::value> * = nullptr> TL_EXPECTED_11_CONSTEXPR U &&operator*() && { + TL_ASSERT(has_value()); return std::move(val()); } @@ -2007,20 +2015,30 @@ class expected : private detail::expected_move_assign_base, return std::move(val()); } - constexpr const E &error() const & { return err().value(); } - TL_EXPECTED_11_CONSTEXPR E &error() & { return err().value(); } - constexpr const E &&error() const && { return std::move(err().value()); } - TL_EXPECTED_11_CONSTEXPR E &&error() && { return std::move(err().value()); } + constexpr const E &error() const & { + TL_ASSERT(!has_value()); + return err().value(); + } + TL_EXPECTED_11_CONSTEXPR E &error() & { + TL_ASSERT(!has_value()); + return err().value(); + } + constexpr const E &&error() const && { + TL_ASSERT(!has_value()); + return std::move(err().value()); + } + TL_EXPECTED_11_CONSTEXPR E &&error() && { + TL_ASSERT(!has_value()); + return std::move(err().value()); + } - template - constexpr T value_or(U &&v) const & { + template constexpr T value_or(U &&v) const & { static_assert(std::is_copy_constructible::value && std::is_convertible::value, "T must be copy-constructible and convertible to from U&&"); return bool(*this) ? **this : static_cast(std::forward(v)); } - template - TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && { + template TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && { static_assert(std::is_move_constructible::value && std::is_convertible::value, "T must be move-constructible and convertible to from U&&"); @@ -2029,12 +2047,9 @@ class expected : private detail::expected_move_assign_base, }; namespace detail { -template -using exp_t = typename detail::decay_t::value_type; -template -using err_t = typename detail::decay_t::error_type; -template -using ret_t = expected>; +template using exp_t = typename detail::decay_t::value_type; +template using err_t = typename detail::decay_t::error_type; +template using ret_t = expected>; #ifdef TL_EXPECTED_CXX14 template (exp).error()); } #else -template -struct TC; +template struct TC; template (), *std::declval())), @@ -2194,7 +2208,7 @@ auto expected_map_impl(Exp &&exp, F &&f) -> expected> { } #endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template >::value> * = nullptr, @@ -2355,7 +2369,7 @@ detail::decay_t or_else_impl(Exp &&exp, F &&f) { std::forward(exp)); } #endif -} // namespace detail +} // namespace detail template constexpr bool operator==(const expected &lhs, @@ -2430,6 +2444,6 @@ void swap(expected &lhs, expected &rhs) noexcept(noexcept(lhs.swap(rhs))) { lhs.swap(rhs); } -} // namespace tl +} // namespace tl #endif