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.
This commit is contained in:
MarcoFalke 2025-12-09 07:50:41 +01:00
parent fa1de1103f
commit fa6575d6c2
No known key found for this signature in database
2 changed files with 24 additions and 6 deletions

View File

@ -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<int, std::string> e{Unexpected{"fail"}};
BOOST_CHECK_THROW(e.value(), BadExpectedAccess);
const Expected<void, std::string> void_e{Unexpected{"fail"}};
BOOST_CHECK_THROW(void_e.value(), BadExpectedAccess);
}
BOOST_AUTO_TEST_CASE(expected_error)
{
Expected<void, std::string> e{};

View File

@ -8,6 +8,7 @@
#include <attributes.h>
#include <cassert>
#include <exception>
#include <type_traits>
#include <utility>
#include <variant>
@ -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