// Copyright (c) The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://opensource.org/license/mit. #ifndef BITCOIN_UTIL_EXPECTED_H #define BITCOIN_UTIL_EXPECTED_H #include #include #include #include #include namespace util { /// The util::Unexpected class represents an unexpected value stored in /// util::Expected. template class Unexpected { public: constexpr explicit Unexpected(E e) : err(std::move(e)) {} E err; }; /// The util::Expected class provides a standard way for low-level functions to /// return either error values or result values. /// /// It provides a smaller version of std::expected from C++23. Missing features /// can be added, if needed. template class Expected { private: using ValueType = std::conditional_t, std::monostate, T>; std::variant m_data; public: constexpr Expected() : m_data{std::in_place_index_t<0>{}, ValueType{}} {} constexpr Expected(ValueType v) : m_data{std::in_place_index_t<0>{}, std::move(v)} {} template constexpr Expected(Unexpected u) : m_data{std::in_place_index_t<1>{}, std::move(u.err)} { } constexpr bool has_value() const noexcept { return m_data.index() == 0; } constexpr explicit operator bool() const noexcept { return has_value(); } constexpr const ValueType& value() const LIFETIMEBOUND { assert(has_value()); return std::get<0>(m_data); } constexpr ValueType& value() LIFETIMEBOUND { assert(has_value()); return std::get<0>(m_data); } template ValueType value_or(U&& default_value) const& { return has_value() ? value() : std::forward(default_value); } template ValueType value_or(U&& default_value) && { 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 ValueType& operator*() LIFETIMEBOUND { return value(); } constexpr const ValueType& operator*() const LIFETIMEBOUND { return value(); } constexpr ValueType* operator->() LIFETIMEBOUND { return &value(); } constexpr const ValueType* operator->() const LIFETIMEBOUND { return &value(); } }; } // namespace util #endif // BITCOIN_UTIL_EXPECTED_H