Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or https://opensource.org/license/mit.5#ifndef BITCOIN_UTIL_EXPECTED_H6#define BITCOIN_UTIL_EXPECTED_H8#include <attributes.h>9#include <util/check.h>11#include <exception>12#include <utility>13#include <variant>15namespace util {17/// The util::Unexpected class represents an unexpected value stored in18/// util::Expected.19template <class E>20class Unexpected21{22public:23constexpr explicit Unexpected(E e) : m_error(std::move(e)) {}25constexpr const E& error() const& noexcept LIFETIMEBOUND { return m_error; }26constexpr E& error() & noexcept LIFETIMEBOUND { return m_error; }27constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(m_error); }29private:30E m_error;31};33struct BadExpectedAccess : std::exception {34const char* what() const noexcept override { return "Bad util::Expected access"; }35};37/// The util::Expected class provides a standard way for low-level functions to38/// return either error values or result values.39///40/// It provides a smaller version of std::expected from C++23. Missing features41/// can be added, if needed.42template <class T, class E>43class Expected44{45private:46std::variant<T, E> m_data;48public:49constexpr Expected() : m_data{std::in_place_index<0>, T{}} {}50constexpr Expected(T v) : m_data{std::in_place_index<0>, std::move(v)} {}51template <class Err>52constexpr Expected(Unexpected<Err> u) : m_data{std::in_place_index<1>, std::move(u).error()}53{54}56constexpr bool has_value() const noexcept { return m_data.index() == 0; }57constexpr explicit operator bool() const noexcept { return has_value(); }59constexpr const T& value() const& LIFETIMEBOUND60{61if (!has_value()) {62throw BadExpectedAccess{};63}64return std::get<0>(m_data);65}66constexpr T& value() & LIFETIMEBOUND67{68if (!has_value()) {69throw BadExpectedAccess{};70}71return std::get<0>(m_data);72}73constexpr T&& value() && LIFETIMEBOUND { return std::move(value()); }75template <class U>76T value_or(U&& default_value) const&77{78return has_value() ? value() : std::forward<U>(default_value);79}80template <class U>81T value_or(U&& default_value) &&82{83return has_value() ? std::move(value()) : std::forward<U>(default_value);84}86constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }87constexpr E& error() & noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }88constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(error()); }90constexpr void swap(Expected& other) noexcept { m_data.swap(other.m_data); }92constexpr T& operator*() & noexcept LIFETIMEBOUND { return value(); }93constexpr const T& operator*() const& noexcept LIFETIMEBOUND { return value(); }94constexpr T&& operator*() && noexcept LIFETIMEBOUND { return std::move(value()); }96constexpr T* operator->() noexcept LIFETIMEBOUND { return &value(); }97constexpr const T* operator->() const noexcept LIFETIMEBOUND { return &value(); }98};100template <class E>101class Expected<void, E>102{103private:104std::variant<std::monostate, E> m_data;106public:107constexpr Expected() : m_data{std::in_place_index<0>, std::monostate{}} {}108template <class Err>109constexpr Expected(Unexpected<Err> u) : m_data{std::in_place_index<1>, std::move(u).error()}110{111}113constexpr bool has_value() const noexcept { return m_data.index() == 0; }114constexpr explicit operator bool() const noexcept { return has_value(); }116constexpr void operator*() const noexcept { return value(); }117constexpr void value() const118{119if (!has_value()) {120throw BadExpectedAccess{};121}122}124constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }125constexpr E& error() & noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }126constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(error()); }127};129} // namespace util131#endif // BITCOIN_UTIL_EXPECTED_H
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.