diff --git a/lib/thirdparty/expected.hpp b/lib/thirdparty/expected.hpp index 31b130a0..7fd64677 100644 --- a/lib/thirdparty/expected.hpp +++ b/lib/thirdparty/expected.hpp @@ -1,6 +1,6 @@ /// // expected - An implementation of std::expected with extensions -// Written in 2017 by Simon Brand (simonrbrand@gmail.com, @TartanLlama) +// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama) // // Documentation available at http://tl.tartanllama.xyz/ // @@ -51,6 +51,16 @@ #define TL_EXPECTED_GCC55 #endif +#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 @@ -66,30 +76,30 @@ #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 std::vector -// for non-copyable types -#elif (defined(__GNUC__) && __GNUC__ < 8 && \ - !defined(__clang__)) +// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks +// std::vector for non-copyable types +#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)) #ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX #define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX namespace tl { - namespace detail { - template - struct is_trivially_copy_constructible : std::is_trivially_copy_constructible{}; +namespace detail { +template +struct is_trivially_copy_constructible + : std::is_trivially_copy_constructible {}; #ifdef _GLIBCXX_VECTOR - template - struct is_trivially_copy_constructible> - : std::false_type{}; +template +struct is_trivially_copy_constructible> : std::false_type {}; #endif - } -} +} // 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) std::is_trivially_destructible +#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \ + std::is_trivially_destructible #else #define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \ std::is_trivially_copy_constructible @@ -138,6 +148,17 @@ public: constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {} + template ::value>::type * = nullptr> + constexpr explicit unexpected(Args &&...args) + : m_val(std::forward(args)...) {} + template < + class U, class... Args, + typename std::enable_if &, Args &&...>::value>::type * = nullptr> + constexpr explicit unexpected(std::initializer_list l, Args &&...args) + : m_val(l, std::forward(args)...) {} + constexpr const E &value() const & { return m_val; } TL_EXPECTED_11_CONSTEXPR E &value() & { return m_val; } TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); } @@ -147,6 +168,10 @@ private: E m_val; }; +#ifdef __cpp_deduction_guides +template unexpected(E) -> unexpected; +#endif + template constexpr bool operator==(const unexpected &lhs, const unexpected &rhs) { return lhs.value() == rhs.value(); @@ -183,16 +208,17 @@ struct unexpect_t { static constexpr unexpect_t unexpect{}; namespace detail { -template +template [[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E &&e) { #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - throw std::forward(e); + throw std::forward(e); #else - #ifdef _MSC_VER - __assume(0); - #else - __builtin_unreachable(); - #endif + (void)e; +#ifdef _MSC_VER + __assume(0); +#else + __builtin_unreachable(); +#endif #endif } @@ -213,7 +239,7 @@ template struct conjunction : std::true_type {}; template struct conjunction : B {}; template struct conjunction - : std::conditional, B>::type {}; + : std::conditional, B>::type {}; #if defined(_LIBCPP_VERSION) && __cplusplus == 201103L #define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND @@ -223,45 +249,52 @@ struct conjunction // which results in a hard-error when using it in a noexcept expression // in some cases. This is a check to workaround the common failing case. #ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND -template struct is_pointer_to_non_const_member_func : std::false_type {}; +template +struct is_pointer_to_non_const_member_func : std::false_type {}; template -struct is_pointer_to_non_const_member_func : std::true_type {}; +struct is_pointer_to_non_const_member_func + : std::true_type {}; template -struct is_pointer_to_non_const_member_func : std::true_type {}; +struct is_pointer_to_non_const_member_func + : std::true_type {}; template -struct is_pointer_to_non_const_member_func : std::true_type {}; +struct is_pointer_to_non_const_member_func + : std::true_type {}; template -struct is_pointer_to_non_const_member_func : std::true_type {}; +struct is_pointer_to_non_const_member_func + : std::true_type {}; template -struct is_pointer_to_non_const_member_func : std::true_type {}; +struct is_pointer_to_non_const_member_func + : std::true_type {}; template -struct is_pointer_to_non_const_member_func : std::true_type {}; +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::true_type {}; #endif // std::invoke from C++17 // https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround -template ::value - && is_const_or_const_ref::value)>, + typename = enable_if_t::value && + is_const_or_const_ref::value)>, #endif - typename = enable_if_t>::value>, - int = 0> - constexpr auto invoke(Fn && f, Args && ... args) noexcept( + typename = enable_if_t>::value>, int = 0> +constexpr auto invoke(Fn &&f, Args &&...args) noexcept( noexcept(std::mem_fn(f)(std::forward(args)...))) - -> decltype(std::mem_fn(f)(std::forward(args)...)) { + -> decltype(std::mem_fn(f)(std::forward(args)...)) { return std::mem_fn(f)(std::forward(args)...); } template >::value>> - constexpr auto invoke(Fn && f, Args && ... args) noexcept( + typename = enable_if_t>::value>> +constexpr auto invoke(Fn &&f, Args &&...args) noexcept( noexcept(std::forward(f)(std::forward(args)...))) - -> decltype(std::forward(f)(std::forward(args)...)) { + -> decltype(std::forward(f)(std::forward(args)...)) { return std::forward(f)(std::forward(args)...); } @@ -270,9 +303,11 @@ template struct invoke_result_impl; template struct invoke_result_impl< - F, decltype(detail::invoke(std::declval(), std::declval()...), void()), - Us...> { - using type = decltype(detail::invoke(std::declval(), std::declval()...)); + F, + decltype(detail::invoke(std::declval(), std::declval()...), void()), + Us...> { + using type = + decltype(detail::invoke(std::declval(), std::declval()...)); }; template @@ -289,69 +324,67 @@ 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 { - // if swap ADL finds this then it would call std::swap otherwise (same - // signature) - struct tag {}; +// if swap ADL finds this then it would call std::swap otherwise (same +// 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::declval()))> - std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), - std::declval()))); +// 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::declval()))> +std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), + std::declval()))); - template std::false_type uses_std(...); - template - std::is_same(), std::declval())), tag> - uses_std(int); +template std::false_type uses_std(...); +template +std::is_same(), std::declval())), tag> +uses_std(int); - template - struct is_std_swap_noexcept +template +struct is_std_swap_noexcept : std::integral_constant::value&& - std::is_nothrow_move_assignable::value> {}; + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value> {}; - template - struct is_std_swap_noexcept : is_std_swap_noexcept {}; +template +struct is_std_swap_noexcept : is_std_swap_noexcept {}; - template - struct is_adl_swap_noexcept +template +struct is_adl_swap_noexcept : std::integral_constant(0))> {}; } // namespace swap_adl_tests template struct is_swappable - : std::integral_constant< - bool, - decltype(detail::swap_adl_tests::can_swap(0))::value && - (!decltype(detail::swap_adl_tests::uses_std(0))::value || - (std::is_move_assignable::value && - std::is_move_constructible::value))> {}; + : std::integral_constant< + bool, + decltype(detail::swap_adl_tests::can_swap(0))::value && + (!decltype(detail::swap_adl_tests::uses_std(0))::value || + (std::is_move_assignable::value && + std::is_move_constructible::value))> {}; template struct is_swappable - : std::integral_constant< - bool, - decltype(detail::swap_adl_tests::can_swap(0))::value && - (!decltype( - detail::swap_adl_tests::uses_std(0))::value || - is_swappable::value)> {}; + : std::integral_constant< + bool, + decltype(detail::swap_adl_tests::can_swap(0))::value && + (!decltype(detail::swap_adl_tests::uses_std( + 0))::value || + is_swappable::value)> {}; template struct is_nothrow_swappable - : std::integral_constant< - bool, - is_swappable::value && - ((decltype(detail::swap_adl_tests::uses_std(0))::value - && detail::swap_adl_tests::is_std_swap_noexcept::value) || - (!decltype(detail::swap_adl_tests::uses_std(0))::value && - detail::swap_adl_tests::is_adl_swap_noexcept::value))> { -}; + : std::integral_constant< + bool, + is_swappable::value && + ((decltype(detail::swap_adl_tests::uses_std(0))::value && + detail::swap_adl_tests::is_std_swap_noexcept::value) || + (!decltype(detail::swap_adl_tests::uses_std(0))::value && + detail::swap_adl_tests::is_adl_swap_noexcept::value))> {}; #endif #endif @@ -393,14 +426,10 @@ using is_move_constructible_or_void = is_void_or>; template -using is_copy_assignable_or_void = - is_void_or>; - +using is_copy_assignable_or_void = is_void_or>; template -using is_move_assignable_or_void = - is_void_or>; - +using is_move_assignable_or_void = is_void_or>; } // namespace detail @@ -423,19 +452,19 @@ struct expected_storage_base { template ::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args &&... args) + constexpr expected_storage_base(in_place_t, Args &&...args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args &&...>::value> * = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&... args) + Args &&...args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -470,19 +499,19 @@ template struct expected_storage_base { template ::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args &&... args) + constexpr expected_storage_base(in_place_t, Args &&...args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args &&...>::value> * = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&... args) + Args &&...args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template struct expected_storage_base { E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() = default; @@ -511,19 +540,19 @@ template struct expected_storage_base { template ::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args &&... args) + constexpr expected_storage_base(in_place_t, Args &&...args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args &&...>::value> * = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&... args) + Args &&...args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template struct expected_storage_base { E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -556,19 +585,19 @@ template struct expected_storage_base { template ::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args &&... args) + constexpr expected_storage_base(in_place_t, Args &&...args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args &&...>::value> * = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&... args) + Args &&...args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template struct expected_storage_base { E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -594,7 +623,13 @@ template struct expected_storage_base { // `T` is `void`, `E` is trivially-destructible template struct expected_storage_base { - TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base() : m_has_val(true) {} + #if __GNUC__ <= 5 + //no constexpr for GCC 4/5 bug + #else + TL_EXPECTED_MSVC2015_CONSTEXPR + #endif + expected_storage_base() : m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {} constexpr expected_storage_base(in_place_t) : m_has_val(true) {} @@ -602,7 +637,7 @@ template struct expected_storage_base { template ::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template struct expected_storage_base { E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() = default; @@ -632,7 +667,7 @@ template struct expected_storage_base { template ::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template struct expected_storage_base { E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -662,7 +697,7 @@ 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; } @@ -672,13 +707,13 @@ struct expected_operations_base : expected_storage_base { 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; } - #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED // These assign overloads ensure that the most efficient assignment // implementation is used while maintaining the strong exception guarantee. @@ -778,7 +813,7 @@ struct expected_operations_base : expected_storage_base { } } - #else +#else // If exceptions are disabled then we can just copy-construct void assign(const expected_operations_base &rhs) noexcept { @@ -795,11 +830,11 @@ struct expected_operations_base : expected_storage_base { geterr().~unexpected(); construct(std::move(rhs).get()); } else { - assign_common(rhs); + assign_common(std::move(rhs)); } } - #endif +#endif // The common part of move/copy assigning template void assign_common(Rhs &&rhs) { @@ -807,7 +842,7 @@ struct expected_operations_base : expected_storage_base { if (rhs.m_has_val) { get() = std::forward(rhs).get(); } else { - destroy_val(); + destroy_val(); construct_error(std::forward(rhs).geterr()); } } else { @@ -839,9 +874,7 @@ struct expected_operations_base : expected_storage_base { } #endif - TL_EXPECTED_11_CONSTEXPR void destroy_val() { - get().~T(); - } + TL_EXPECTED_11_CONSTEXPR void destroy_val() { get().~T(); } }; // This base class provides some handy member functions which can be used in @@ -858,7 +891,7 @@ struct expected_operations_base : expected_storage_base { 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; @@ -895,7 +928,7 @@ struct expected_operations_base : expected_storage_base { #endif TL_EXPECTED_11_CONSTEXPR void destroy_val() { - //no-op + // no-op } }; @@ -1220,14 +1253,17 @@ class expected : private detail::expected_move_assign_base, "T must not be in_place_t"); static_assert(!std::is_same::type>::value, "T must not be unexpect_t"); - static_assert(!std::is_same>::type>::value, - "T must not be unexpected"); + static_assert( + !std::is_same>::type>::value, + "T must not be unexpected"); static_assert(!std::is_reference::value, "E must not be a reference"); T *valptr() { return std::addressof(this->m_val); } - const T *valptr() const { return std::addressof(this->m_val); } + const T *valptr() const { return std::addressof(this->m_val); } unexpected *errptr() { return std::addressof(this->m_unexpect); } - const unexpected *errptr() const { return std::addressof(this->m_unexpect); } + const unexpected *errptr() const { + return std::addressof(this->m_unexpect); + } template ::value> * = nullptr> @@ -1272,24 +1308,26 @@ public: #else template TL_EXPECTED_11_CONSTEXPR auto - and_then(F &&f) & -> decltype(and_then_impl(std::declval(), std::forward(f))) { + 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 - constexpr auto and_then(F &&f) const & -> decltype( - and_then_impl(std::declval(), std::forward(f))) { + constexpr auto and_then(F &&f) const & -> decltype(and_then_impl( + std::declval(), std::forward(f))) { return and_then_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr auto and_then(F &&f) const && -> decltype( - and_then_impl(std::declval(), std::forward(f))) { + constexpr auto and_then(F &&f) const && -> decltype(and_then_impl( + std::declval(), std::forward(f))) { return and_then_impl(std::move(*this), std::forward(f)); } #endif @@ -1297,7 +1335,7 @@ public: #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) && { @@ -1311,14 +1349,14 @@ public: } #else template - TL_EXPECTED_11_CONSTEXPR decltype( - expected_map_impl(std::declval(), std::declval())) + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl( + std::declval(), std::declval())) map(F &&f) & { return expected_map_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR decltype( - expected_map_impl(std::declval(), std::declval())) + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), + std::declval())) map(F &&f) && { return expected_map_impl(std::move(*this), std::forward(f)); } @@ -1341,7 +1379,7 @@ public: #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) && { @@ -1354,15 +1392,15 @@ public: return expected_map_impl(std::move(*this), std::forward(f)); } #else - template - TL_EXPECTED_11_CONSTEXPR decltype( - expected_map_impl(std::declval(), std::declval())) + template + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl( + std::declval(), std::declval())) transform(F &&f) & { return expected_map_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR decltype( - expected_map_impl(std::declval(), std::declval())) + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), + std::declval())) transform(F &&f) && { return expected_map_impl(std::move(*this), std::forward(f)); } @@ -1425,6 +1463,49 @@ public: return map_error_impl(std::move(*this), std::forward(f)); } #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 + 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 + 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)); @@ -1452,14 +1533,14 @@ public: template ::value> * = nullptr> - constexpr expected(in_place_t, Args &&... args) + constexpr expected(in_place_t, Args &&...args) : impl_base(in_place, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} template &, Args &&...>::value> * = nullptr> - constexpr expected(in_place_t, std::initializer_list il, Args &&... args) + constexpr expected(in_place_t, std::initializer_list il, Args &&...args) : impl_base(in_place, il, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} @@ -1472,7 +1553,7 @@ public: : impl_base(unexpect, e.value()), ctor_base(detail::default_constructor_tag{}) {} - template < + template < class G = E, detail::enable_if_t::value> * = nullptr, @@ -1490,7 +1571,7 @@ public: : impl_base(unexpect, std::move(e.value())), ctor_base(detail::default_constructor_tag{}) {} - template < + template < class G = E, detail::enable_if_t::value> * = nullptr, detail::enable_if_t::value> * = nullptr> @@ -1502,15 +1583,15 @@ public: template ::value> * = nullptr> - constexpr explicit expected(unexpect_t, Args &&... args) + constexpr explicit expected(unexpect_t, Args &&...args) : impl_base(unexpect, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} - template &, Args &&...>::value> * = nullptr> constexpr explicit expected(unexpect_t, std::initializer_list il, - Args &&... args) + Args &&...args) : impl_base(unexpect, il, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} @@ -1525,11 +1606,11 @@ public: if (rhs.has_value()) { this->construct(*rhs); } else { - this->construct_error(rhs.error()); + this->construct_error(rhs.error()); } } - template ::value && std::is_convertible::value)> * = nullptr, @@ -1540,8 +1621,8 @@ public: if (rhs.has_value()) { this->construct(*rhs); } else { - this->construct_error(rhs.error()); - } + this->construct_error(rhs.error()); + } } template < @@ -1554,11 +1635,11 @@ public: if (rhs.has_value()) { this->construct(std::move(*rhs)); } else { - this->construct_error(std::move(rhs.error())); - } + this->construct_error(std::move(rhs.error())); + } } - template < + template < class U, class G, detail::enable_if_t<(std::is_convertible::value && std::is_convertible::value)> * = nullptr, @@ -1568,8 +1649,8 @@ public: if (rhs.has_value()) { this->construct(std::move(*rhs)); } else { - this->construct_error(std::move(rhs.error())); - } + this->construct_error(std::move(rhs.error())); + } } template < @@ -1579,7 +1660,7 @@ public: explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) : expected(in_place, std::forward(v)) {} - template < + template < class U = T, detail::enable_if_t::value> * = nullptr, detail::expected_enable_forward_value * = nullptr> @@ -1610,7 +1691,7 @@ public: return *this; } - template < + template < class U = T, class G = T, detail::enable_if_t::value> * = nullptr, @@ -1629,7 +1710,7 @@ public: auto tmp = std::move(err()); err().~unexpected(); - #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED try { ::new (valptr()) T(std::forward(v)); this->m_has_val = true; @@ -1637,10 +1718,10 @@ public: err() = std::move(tmp); throw; } - #else - ::new (valptr()) T(std::forward(v)); - this->m_has_val = true; - #endif +#else + ::new (valptr()) T(std::forward(v)); + this->m_has_val = true; +#endif } return *this; @@ -1678,26 +1759,27 @@ public: template ::value> * = nullptr> - void emplace(Args &&... args) { + void emplace(Args &&...args) { if (has_value()) { - val() = T(std::forward(args)...); + val().~T(); } else { err().~unexpected(); - ::new (valptr()) T(std::forward(args)...); this->m_has_val = true; } + ::new (valptr()) T(std::forward(args)...); } - template ::value> * = nullptr> - void emplace(Args &&... args) { + void emplace(Args &&...args) { if (has_value()) { - val() = T(std::forward(args)...); + val().~T(); + ::new (valptr()) T(std::forward(args)...); } else { auto tmp = std::move(err()); err().~unexpected(); - #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED try { ::new (valptr()) T(std::forward(args)...); this->m_has_val = true; @@ -1705,17 +1787,17 @@ public: err() = std::move(tmp); throw; } - #else +#else ::new (valptr()) T(std::forward(args)...); this->m_has_val = true; - #endif +#endif } } template &, Args &&...>::value> * = nullptr> - void emplace(std::initializer_list il, Args &&... args) { + void emplace(std::initializer_list il, Args &&...args) { if (has_value()) { T t(il, std::forward(args)...); val() = std::move(t); @@ -1726,10 +1808,10 @@ public: } } - template &, Args &&...>::value> * = nullptr> - void emplace(std::initializer_list il, Args &&... args) { + void emplace(std::initializer_list il, Args &&...args) { if (has_value()) { T t(il, std::forward(args)...); val() = std::move(t); @@ -1737,7 +1819,7 @@ public: auto tmp = std::move(err()); err().~unexpected(); - #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED try { ::new (valptr()) T(il, std::forward(args)...); this->m_has_val = true; @@ -1745,10 +1827,10 @@ public: err() = std::move(tmp); throw; } - #else +#else ::new (valptr()) T(il, std::forward(args)...); this->m_has_val = true; - #endif +#endif } } @@ -1760,7 +1842,7 @@ private: using e_is_nothrow_move_constructible = std::true_type; using move_constructing_e_can_throw = std::false_type; - void swap_where_both_have_value(expected &/*rhs*/ , t_is_void) noexcept { + void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept { // swapping void is a no-op } @@ -1818,12 +1900,12 @@ private: void swap_where_only_one_has_value_and_t_is_not_void( expected &rhs, move_constructing_t_can_throw, - t_is_nothrow_move_constructible) { + e_is_nothrow_move_constructible) { auto temp = std::move(rhs.err()); rhs.err().~unexpected_type(); #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED try { - ::new (rhs.valptr()) T(val()); + ::new (rhs.valptr()) T(std::move(val())); val().~T(); ::new (errptr()) unexpected_type(std::move(temp)); std::swap(this->m_has_val, rhs.m_has_val); @@ -1832,7 +1914,7 @@ private: throw; } #else - ::new (rhs.valptr()) T(val()); + ::new (rhs.valptr()) T(std::move(val())); val().~T(); ::new (errptr()) unexpected_type(std::move(temp)); std::swap(this->m_has_val, rhs.m_has_val); @@ -1862,27 +1944,37 @@ public: } } - 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()); } @@ -1918,10 +2010,22 @@ public: 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 & { static_assert(std::is_copy_constructible::value && @@ -1991,7 +2095,7 @@ constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret { #ifdef TL_EXPECTED_CXX14 template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), detail::enable_if_t::value> * = nullptr> @@ -2003,7 +2107,7 @@ constexpr auto expected_map_impl(Exp &&exp, F &&f) { } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), detail::enable_if_t::value> * = nullptr> @@ -2028,7 +2132,7 @@ constexpr auto expected_map_impl(Exp &&exp, F &&f) { } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval())), detail::enable_if_t::value> * = nullptr> auto expected_map_impl(Exp &&exp, F &&f) { @@ -2039,10 +2143,10 @@ auto expected_map_impl(Exp &&exp, F &&f) { } return result(unexpect, std::forward(exp).error()); -} +} #else template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), detail::enable_if_t::value> * = nullptr> @@ -2057,7 +2161,7 @@ constexpr auto expected_map_impl(Exp &&exp, F &&f) } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), detail::enable_if_t::value> * = nullptr> @@ -2072,7 +2176,7 @@ auto expected_map_impl(Exp &&exp, F &&f) -> expected> { } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval())), detail::enable_if_t::value> * = nullptr> @@ -2085,7 +2189,7 @@ constexpr auto expected_map_impl(Exp &&exp, F &&f) } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval())), detail::enable_if_t::value> * = nullptr> @@ -2096,13 +2200,13 @@ auto expected_map_impl(Exp &&exp, F &&f) -> expected> { } return unexpected>(std::forward(exp).error()); -} +} #endif #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2114,7 +2218,7 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) { std::forward(exp).error())); } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2128,7 +2232,7 @@ auto map_error_impl(Exp &&exp, F &&f) { return result(unexpect, monostate{}); } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2140,7 +2244,7 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) { std::forward(exp).error())); } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2152,10 +2256,10 @@ auto map_error_impl(Exp &&exp, F &&f) { detail::invoke(std::forward(f), std::forward(exp).error()); return result(unexpect, monostate{}); -} +} #else template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2170,7 +2274,7 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2185,7 +2289,7 @@ auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2200,7 +2304,7 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) } template >::value> * = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2212,7 +2316,7 @@ auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { detail::invoke(std::forward(f), std::forward(exp).error()); return result(unexpect, monostate{}); -} +} #endif #ifdef TL_EXPECTED_CXX14 @@ -2222,9 +2326,9 @@ template ::value> * = nullptr> constexpr auto or_else_impl(Exp &&exp, F &&f) { static_assert(detail::is_expected::value, "F must return an expected"); - return exp.has_value() - ? std::forward(exp) - : detail::invoke(std::forward(f), std::forward(exp).error()); + return exp.has_value() ? std::forward(exp) + : detail::invoke(std::forward(f), + std::forward(exp).error()); } template ().error())), detail::enable_if_t::value> * = nullptr> detail::decay_t or_else_impl(Exp &&exp, F &&f) { - return exp.has_value() - ? std::forward(exp) - : (detail::invoke(std::forward(f), std::forward(exp).error()), - std::forward(exp)); + return exp.has_value() ? std::forward(exp) + : (detail::invoke(std::forward(f), + std::forward(exp).error()), + std::forward(exp)); } #else template (), std::declval().error())), - detail::enable_if_t::value> * = nullptr> + detail::enable_if_t::value> * = nullptr> auto or_else_impl(Exp &&exp, F &&f) -> Ret { static_assert(detail::is_expected::value, "F must return an expected"); - return exp.has_value() - ? std::forward(exp) - : detail::invoke(std::forward(f), std::forward(exp).error()); + return exp.has_value() ? std::forward(exp) + : detail::invoke(std::forward(f), + std::forward(exp).error()); } template (), std::declval().error())), - detail::enable_if_t::value> * = nullptr> + detail::enable_if_t::value> * = nullptr> detail::decay_t or_else_impl(Exp &&exp, F &&f) { - return exp.has_value() - ? std::forward(exp) - : (detail::invoke(std::forward(f), std::forward(exp).error()), - std::forward(exp)); + return exp.has_value() ? std::forward(exp) + : (detail::invoke(std::forward(f), + std::forward(exp).error()), + std::forward(exp)); } #endif } // namespace detail @@ -2276,6 +2380,20 @@ constexpr bool operator!=(const expected &lhs, ? true : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs); } +template +constexpr bool operator==(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? false + : (!lhs.has_value() ? lhs.error() == rhs.error() : true); +} +template +constexpr bool operator!=(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? true + : (!lhs.has_value() ? lhs.error() == rhs.error() : false); +} template constexpr bool operator==(const expected &x, const U &v) { diff --git a/lib/thirdparty/optional.hpp b/lib/thirdparty/optional.hpp index 37b774a6..e9c59c26 100644 --- a/lib/thirdparty/optional.hpp +++ b/lib/thirdparty/optional.hpp @@ -18,7 +18,7 @@ #define TL_OPTIONAL_HPP #define TL_OPTIONAL_VERSION_MAJOR 1 -#define TL_OPTIONAL_VERSION_MINOR 0 +#define TL_OPTIONAL_VERSION_MINOR 1 #define TL_OPTIONAL_VERSION_PATCH 0 #include @@ -409,7 +409,7 @@ template struct optional_operations_base : optional_storage_base { this->m_has_value = false; } - template void construct(Args &&... args) noexcept { + template void construct(Args &&... args) { new (std::addressof(this->m_value)) T(std::forward(args)...); this->m_has_value = true; } @@ -742,8 +742,7 @@ public: static_assert(detail::is_optional::value, "F must return an optional"); - return has_value() ? detail::invoke(std::forward(f), **this) - : result(nullopt); + return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); } template @@ -1183,7 +1182,7 @@ public: } } - if (rhs.has_value()) { + else if (rhs.has_value()) { this->construct(*rhs); } @@ -1205,7 +1204,7 @@ public: } } - if (rhs.has_value()) { + else if (rhs.has_value()) { this->construct(std::move(*rhs)); } @@ -1323,7 +1322,7 @@ public: static_assert(std::is_move_constructible::value && std::is_convertible::value, "T must be move constructible and convertible from U"); - return has_value() ? **this : static_cast(std::forward(u)); + return has_value() ? std::move(**this) : static_cast(std::forward(u)); } /// Destroys the stored value if one exists, making the optional empty @@ -1646,7 +1645,7 @@ public: static_assert(detail::is_optional::value, "F must return an optional"); - return has_value() ? detail::invoke(std::forward(f), **this) + return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : result(nullopt); } #endif