util: Implement Expected::operator*()&&
What changed, and why it matters
This commit adds a new C++ language feature to Bitcoin Core's custom Expected helper class: the ability to safely move a value out of a temporary Expected object when using the * operator. It also adds a unit test. There is no security issue here; it is a routine code-quality and standards-conformance improvement.
No security action required. Review as normal C++ utility code.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch implements Expected::operator()&&, the rvalue-qualified dereference overload, mirroring std::expected. It refines the existing lvalue and const-lvalue overloads by adding &/const& qualifiers and adds a test that moves a std::unique_ptr out of an Expected via std::move(expected). The change is currently unused in production code and introduces no behavioral change to existing callers.
Changed components
src/util/expected.hsrc/test/util_expected_tests.cppInspect captured patch +10 / −2
diff --git a/src/test/util_expected_tests.cpp b/src/test/util_expected_tests.cpp
index 7c9d62ad..356735b2 100644
--- a/src/test/util_expected_tests.cpp
+++ b/src/test/util_expected_tests.cpp
@@ -50,6 +50,13 @@ BOOST_AUTO_TEST_CASE(expected_value_rvalue)
BOOST_CHECK_EQUAL(*moved, 5);
}
+BOOST_AUTO_TEST_CASE(expected_deref_rvalue)
+{
+ Expected<std::unique_ptr<int>, int> no_copy{std::make_unique<int>(5)};
+ const auto moved{*std::move(no_copy)};
+ BOOST_CHECK_EQUAL(*moved, 5);
+}
+
BOOST_AUTO_TEST_CASE(expected_value_or)
{
Expected<std::unique_ptr<int>, int> no_copy{std::make_unique<int>(1)};
diff --git a/src/util/expected.h b/src/util/expected.h
index 85d4bf9d..b01d866a 100644
--- a/src/util/expected.h
+++ b/src/util/expected.h
@@ -88,8 +88,9 @@ public:
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(); }
+ constexpr T& operator*() & noexcept LIFETIMEBOUND { return value(); }
+ constexpr const T& operator*() const& noexcept LIFETIMEBOUND { return value(); }
+ constexpr T&& operator*() && noexcept LIFETIMEBOUND { return std::move(value()); }
constexpr T* operator->() noexcept LIFETIMEBOUND { return &value(); }
constexpr const T* operator->() const noexcept LIFETIMEBOUND { return &value(); }
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.