brace
Incredibly simple JSON parser in C++
Loading...
Searching...
No Matches
result.h
1#ifndef BRACE_RESULT_H
2#define BRACE_RESULT_H
3
4#include <assert.h>
5
6#include <iostream>
7#include <stdexcept>
8#include <type_traits>
9#include <variant>
10
11namespace brace {
12
13struct Unit {};
14
15template<typename T, typename E>
16class [[nodiscard]] Result {
17 public:
18 Result(const T& value) : Result(ok_tag {}, value) {}
19
20 Result(T&& value) : Result(ok_tag {}, std::move(value)) {}
21
22 template<typename U = E, typename = std::enable_if_t<!std::is_same_v<T, U>>>
23 Result(const E& error) : Result(err_tag {}, error) {}
24
25 template<typename U = E, typename = std::enable_if_t<!std::is_same_v<T, U>>>
26 Result(E&& error) : Result(err_tag {}, std::move(error)) {}
27
28 bool is_ok() const {
29 return std::holds_alternative<T>(m_data);
30 }
31
32 bool is_err() const {
33 return std::holds_alternative<E>(m_data);
34 }
35
36 const T& expect(const std::string& message) const& {
37 if (is_ok()) {
38 return unwrap();
39 }
40 printf("%s: %s\n", message, unwrap_err().message().c_str());
41 std::abort();
42 }
43
44 T&& expect(const std::string& message) && {
45 if (is_ok()) {
46 return std::move(*this).unwrap();
47 }
48 printf("%s: %s\n", message, unwrap_err().message().c_str());
49 std::abort();
50 }
51
52 const T& unwrap() const& {
53 if (!is_ok()) {
54 std::cout << "Called unwrap on an Err value:"
55 << unwrap_err().message() << "\n";
56 std::abort();
57 }
58 return std::get<T>(m_data);
59 }
60
61 T&& unwrap() && {
62 if (!is_ok()) {
63 std::cout << "Called unwrap on an Err value:"
64 << unwrap_err().message() << "\n";
65 std::abort();
66 }
67 return std::move(std::get<T>(m_data));
68 }
69
70 const T& unwrap_ok() const& {
71 return unwrap();
72 }
73
74 T&& unwrap_ok() && {
75 return std::move(*this).unwrap();
76 }
77
78 const E& unwrap_err() const& {
79 assert(is_err() && "Called unwrap_err on an Ok value");
80 return std::get<E>(m_data);
81 }
82
83 E&& unwrap_err() && {
84 assert(is_err() && "Called unwrap_err on an Ok value");
85 return std::move(std::get<E>(m_data));
86 }
87
88 template<typename F>
89 auto map(F&& f) const -> Result<decltype(f(std::declval<T>())), E> {
90 if (is_ok()) {
91 return Result<decltype(f(std::declval<T>())), E>(f(unwrap()));
92 }
93 return Result<decltype(f(std::declval<T>())), E>(unwrap_err());
94 }
95
96 template<typename F>
97 auto map_err(F&& f) const -> Result<T, decltype(f(std::declval<E>()))> {
98 if (is_err()) {
99 return Result<T, decltype(f(std::declval<E>()))>(f(unwrap_err()));
100 }
101 return Result<T, decltype(f(std::declval<E>()))>(unwrap());
102 }
103
104 template<typename F>
105 auto and_then(F&& f) const {
106 if (is_ok()) {
107 if constexpr (is_result<decltype(f(std::declval<T>()))>::value) {
108 return f(unwrap());
109 } else {
110 return Result<decltype(f(std::declval<T>())), E>(f(unwrap()));
111 }
112 }
113 return Result<decltype(f(std::declval<T>())), E>(unwrap_err());
114 }
115
116 template<typename U>
117 T unwrap_or(U&& default_value) const {
118 if (is_ok()) {
119 return unwrap();
120 }
121 return static_cast<T>(std::forward<U>(default_value));
122 }
123
124 template<typename F>
125 T unwrap_or_else(F&& f) const {
126 if (is_ok()) {
127 return unwrap();
128 }
129 return f(unwrap_err());
130 }
131
132 private:
133 std::variant<T, E> m_data;
134
135 struct ok_tag {};
136
137 struct err_tag {};
138
139 template<typename U>
140 struct is_result: std::false_type {};
141
142 template<typename U, typename V>
143 struct is_result<Result<U, V>>: std::true_type {};
144
145 Result(ok_tag, const T& value) : m_data(value) {}
146
147 Result(ok_tag, T&& value) : m_data(std::move(value)) {}
148
149 Result(err_tag, const E& error) : m_data(error) {}
150
151 Result(err_tag, E&& error) : m_data(std::move(error)) {}
152};
153
154template<typename T, typename E>
155Result<T, E> Ok(T&& value) {
156 return Result<T, E>(std::forward<T>(value));
157}
158
159template<typename T, typename E>
160Result<T, E> Err(E&& error) {
161 return Result<T, E>(std::forward<E>(error));
162}
163
164#if defined(_MSC_VER)
165 #define TRY(expr) \
166 do { \
167 auto&& _result = (expr); \
168 if (!_result.is_ok()) \
169 return std::move(_result).unwrap_err(); \
170 _result.unwrap(); \
171 } while (0)
172#else
173 #define TRY(expr) \
174 ({ \
175 auto _result = (expr); \
176 if (!_result.is_ok()) \
177 return _result.unwrap_err(); \
178 _result.unwrap(); \
179 })
180#endif
181
182} // namespace brace
183
184#endif
Definition result.h:16
Definition result.h:13