Bitcoin Core 30.99.0
P2P Digital Currency
expected.h
Go to the documentation of this file.
1// Copyright (c) The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or https://opensource.org/license/mit.
4
5#ifndef BITCOIN_UTIL_EXPECTED_H
6#define BITCOIN_UTIL_EXPECTED_H
7
8#include <attributes.h>
9#include <util/check.h>
10
11#include <cassert>
12#include <exception>
13#include <utility>
14#include <variant>
15
16namespace util {
17
20template <class E>
22{
23public:
24 constexpr explicit Unexpected(E e) : m_error(std::move(e)) {}
25
26 constexpr const E& error() const& noexcept LIFETIMEBOUND { return m_error; }
27 constexpr E& error() & noexcept LIFETIMEBOUND { return m_error; }
28 constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(m_error); }
29
30private:
32};
33
34struct BadExpectedAccess : std::exception {
35 const char* what() const noexcept override { return "Bad util::Expected access"; }
36};
37
43template <class T, class E>
45{
46private:
47 std::variant<T, E> m_data;
48
49public:
50 constexpr Expected() : m_data{std::in_place_index<0>, T{}} {}
51 constexpr Expected(T v) : m_data{std::in_place_index<0>, std::move(v)} {}
52 template <class Err>
53 constexpr Expected(Unexpected<Err> u) : m_data{std::in_place_index<1>, std::move(u).error()}
54 {
55 }
56
57 constexpr bool has_value() const noexcept { return m_data.index() == 0; }
58 constexpr explicit operator bool() const noexcept { return has_value(); }
59
60 constexpr const T& value() const& LIFETIMEBOUND
61 {
62 if (!has_value()) {
63 throw BadExpectedAccess{};
64 }
65 return std::get<0>(m_data);
66 }
67 constexpr T& value() & LIFETIMEBOUND
68 {
69 if (!has_value()) {
70 throw BadExpectedAccess{};
71 }
72 return std::get<0>(m_data);
73 }
74 constexpr T&& value() && LIFETIMEBOUND { return std::move(value()); }
75
76 template <class U>
77 T value_or(U&& default_value) const&
78 {
79 return has_value() ? value() : std::forward<U>(default_value);
80 }
81 template <class U>
82 T value_or(U&& default_value) &&
83 {
84 return has_value() ? std::move(value()) : std::forward<U>(default_value);
85 }
86
87 constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
88 constexpr E& error() & noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
89 constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(error()); }
90
91 constexpr void swap(Expected& other) noexcept { m_data.swap(other.m_data); }
92
93 constexpr T& operator*() & noexcept LIFETIMEBOUND { return value(); }
94 constexpr const T& operator*() const& noexcept LIFETIMEBOUND { return value(); }
95 constexpr T&& operator*() && noexcept LIFETIMEBOUND { return std::move(value()); }
96
97 constexpr T* operator->() noexcept LIFETIMEBOUND { return &value(); }
98 constexpr const T* operator->() const noexcept LIFETIMEBOUND { return &value(); }
99};
100
101template <class E>
102class Expected<void, E>
103{
104private:
105 std::variant<std::monostate, E> m_data;
106
107public:
108 constexpr Expected() : m_data{std::in_place_index<0>, std::monostate{}} {}
109 template <class Err>
110 constexpr Expected(Unexpected<Err> u) : m_data{std::in_place_index<1>, std::move(u).error()}
111 {
112 }
113
114 constexpr bool has_value() const noexcept { return m_data.index() == 0; }
115 constexpr explicit operator bool() const noexcept { return has_value(); }
116
117 constexpr void operator*() const noexcept { return value(); }
118 constexpr void value() const
119 {
120 if (!has_value()) {
121 throw BadExpectedAccess{};
122 }
123 }
124
125 constexpr const E& error() const& noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
126 constexpr E& error() & noexcept LIFETIMEBOUND { return *Assert(std::get_if<1>(&m_data)); }
127 constexpr E&& error() && noexcept LIFETIMEBOUND { return std::move(error()); }
128};
129
130} // namespace util
131
132#endif // BITCOIN_UTIL_EXPECTED_H
#define LIFETIMEBOUND
Definition: attributes.h:16
#define Assert(val)
Identity function.
Definition: check.h:113
constexpr bool has_value() const noexcept
Definition: expected.h:114
constexpr void value() const
Definition: expected.h:118
constexpr Expected(Unexpected< Err > u)
Definition: expected.h:110
std::variant< std::monostate, E > m_data
Definition: expected.h:105
constexpr const E & error() const &noexcept LIFETIMEBOUND
Definition: expected.h:125
constexpr void operator*() const noexcept
Definition: expected.h:117
constexpr E & error() &noexcept LIFETIMEBOUND
Definition: expected.h:126
constexpr E && error() &&noexcept LIFETIMEBOUND
Definition: expected.h:127
The util::Expected class provides a standard way for low-level functions to return either error value...
Definition: expected.h:45
constexpr T & operator*() &noexcept LIFETIMEBOUND
Definition: expected.h:93
T value_or(U &&default_value) const &
Definition: expected.h:77
constexpr const T * operator->() const noexcept LIFETIMEBOUND
Definition: expected.h:98
constexpr E && error() &&noexcept LIFETIMEBOUND
Definition: expected.h:89
constexpr E & error() &noexcept LIFETIMEBOUND
Definition: expected.h:88
T value_or(U &&default_value) &&
Definition: expected.h:82
std::variant< T, E > m_data
Definition: expected.h:47
constexpr Expected(T v)
Definition: expected.h:51
constexpr T & value() &LIFETIMEBOUND
Definition: expected.h:67
constexpr const T & operator*() const &noexcept LIFETIMEBOUND
Definition: expected.h:94
constexpr T * operator->() noexcept LIFETIMEBOUND
Definition: expected.h:97
constexpr bool has_value() const noexcept
Definition: expected.h:57
constexpr T && value() &&LIFETIMEBOUND
Definition: expected.h:74
constexpr const T & value() const &LIFETIMEBOUND
Definition: expected.h:60
constexpr Expected()
Definition: expected.h:50
constexpr Expected(Unexpected< Err > u)
Definition: expected.h:53
constexpr const E & error() const &noexcept LIFETIMEBOUND
Definition: expected.h:87
constexpr T && operator*() &&noexcept LIFETIMEBOUND
Definition: expected.h:95
constexpr void swap(Expected &other) noexcept
Definition: expected.h:91
The util::Unexpected class represents an unexpected value stored in util::Expected.
Definition: expected.h:22
constexpr E & error() &noexcept LIFETIMEBOUND
Definition: expected.h:27
constexpr const E & error() const &noexcept LIFETIMEBOUND
Definition: expected.h:26
constexpr E && error() &&noexcept LIFETIMEBOUND
Definition: expected.h:28
constexpr Unexpected(E e)
Definition: expected.h:24
#define T(expected, seed, data)
const char * what() const noexcept override
Definition: expected.h:35
#define E
Definition: util_tests.cpp:546