From fa6575d6c2d27d173162888226df669fb8aeea47 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 9 Dec 2025 07:50:41 +0100 Subject: [PATCH] util: Make Expected::value() throw This is not expected to be needed in this codebase, but brings the implementation closer to std::expected::value(). Also, add noexcept, where std::expected has them. This will make operator-> and operator* terminate, when has_value() is false. --- src/test/util_expected_tests.cpp | 9 +++++++++ src/util/expected.h | 21 +++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/test/util_expected_tests.cpp b/src/test/util_expected_tests.cpp index f02ea3fdd70..64f543bf3fd 100644 --- a/src/test/util_expected_tests.cpp +++ b/src/test/util_expected_tests.cpp @@ -53,6 +53,15 @@ BOOST_AUTO_TEST_CASE(expected_value_or) BOOST_CHECK_EQUAL(const_val.value_or("fallback"), "fallback"); } +BOOST_AUTO_TEST_CASE(expected_value_throws) +{ + const Expected e{Unexpected{"fail"}}; + BOOST_CHECK_THROW(e.value(), BadExpectedAccess); + + const Expected void_e{Unexpected{"fail"}}; + BOOST_CHECK_THROW(void_e.value(), BadExpectedAccess); +} + BOOST_AUTO_TEST_CASE(expected_error) { Expected e{}; diff --git a/src/util/expected.h b/src/util/expected.h index 71cd0f941c8..d4611698607 100644 --- a/src/util/expected.h +++ b/src/util/expected.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,10 @@ private: E m_error; }; +struct BadExpectedAccess : std::exception { + const char* what() const noexcept override { return "Bad util::Expected access"; } +}; + /// The util::Expected class provides a standard way for low-level functions to /// return either error values or result values. /// @@ -55,12 +60,16 @@ public: constexpr const ValueType& value() const LIFETIMEBOUND { - assert(has_value()); + if (!has_value()) { + throw BadExpectedAccess{}; + } return std::get<0>(m_data); } constexpr ValueType& value() LIFETIMEBOUND { - assert(has_value()); + if (!has_value()) { + throw BadExpectedAccess{}; + } return std::get<0>(m_data); } @@ -86,11 +95,11 @@ public: return std::get<1>(m_data); } - constexpr ValueType& operator*() LIFETIMEBOUND { return value(); } - constexpr const ValueType& operator*() const LIFETIMEBOUND { return value(); } + constexpr ValueType& operator*() noexcept LIFETIMEBOUND { return value(); } + constexpr const ValueType& operator*() const noexcept LIFETIMEBOUND { return value(); } - constexpr ValueType* operator->() LIFETIMEBOUND { return &value(); } - constexpr const ValueType* operator->() const LIFETIMEBOUND { return &value(); } + constexpr ValueType* operator->() noexcept LIFETIMEBOUND { return &value(); } + constexpr const ValueType* operator->() const noexcept LIFETIMEBOUND { return &value(); } }; } // namespace util