From fab9721430aa83ddb266aca029e270aec81c021d Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 9 Dec 2025 09:26:17 +0100 Subject: [PATCH] util: Implement Expected::value()&& and Expected::error()&& They are currently unused, but implementing them is closer to the std::expected. --- src/test/util_expected_tests.cpp | 21 +++++++++++++++++++++ src/util/expected.h | 18 ++++++------------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/test/util_expected_tests.cpp b/src/test/util_expected_tests.cpp index e626a9887c7..7c9d62ad392 100644 --- a/src/test/util_expected_tests.cpp +++ b/src/test/util_expected_tests.cpp @@ -43,6 +43,13 @@ BOOST_AUTO_TEST_CASE(expected_value) BOOST_CHECK_EQUAL(read->x, 45); } +BOOST_AUTO_TEST_CASE(expected_value_rvalue) +{ + Expected, int> no_copy{std::make_unique(5)}; + const auto moved{std::move(no_copy).value()}; + BOOST_CHECK_EQUAL(*moved, 5); +} + BOOST_AUTO_TEST_CASE(expected_value_or) { Expected, int> no_copy{std::make_unique(1)}; @@ -81,6 +88,20 @@ BOOST_AUTO_TEST_CASE(expected_error) BOOST_CHECK_EQUAL(read.error(), "fail1"); } +BOOST_AUTO_TEST_CASE(expected_error_rvalue) +{ + { + Expected> nocopy_err{Unexpected{std::make_unique(7)}}; + const auto moved{std::move(nocopy_err).error()}; + BOOST_CHECK_EQUAL(*moved, 7); + } + { + Expected> void_nocopy_err{Unexpected{std::make_unique(9)}}; + const auto moved{std::move(void_nocopy_err).error()}; + BOOST_CHECK_EQUAL(*moved, 9); + } +} + BOOST_AUTO_TEST_CASE(unexpected_error_accessors) { Unexpected u{std::make_unique(-1)}; diff --git a/src/util/expected.h b/src/util/expected.h index a7d02c39dcc..85d4bf9d47a 100644 --- a/src/util/expected.h +++ b/src/util/expected.h @@ -57,20 +57,21 @@ public: constexpr bool has_value() const noexcept { return m_data.index() == 0; } constexpr explicit operator bool() const noexcept { return has_value(); } - constexpr const T& value() const LIFETIMEBOUND + constexpr const T& value() const& LIFETIMEBOUND { if (!has_value()) { throw BadExpectedAccess{}; } return std::get<0>(m_data); } - constexpr T& value() LIFETIMEBOUND + constexpr T& value() & LIFETIMEBOUND { if (!has_value()) { throw BadExpectedAccess{}; } return std::get<0>(m_data); } + constexpr T&& value() && LIFETIMEBOUND { return std::move(value()); } template T value_or(U&& default_value) const& @@ -83,16 +84,9 @@ public: return has_value() ? std::move(value()) : std::forward(default_value); } - constexpr const E& error() const LIFETIMEBOUND - { - assert(!has_value()); - return std::get<1>(m_data); - } - constexpr E& error() LIFETIMEBOUND - { - assert(!has_value()); - return std::get<1>(m_data); - } + constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); } + constexpr E& error() & noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); } + constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(error()); } constexpr T& operator*() noexcept LIFETIMEBOUND { return value(); } constexpr const T& operator*() const noexcept LIFETIMEBOUND { return value(); }