Octane API Client
Loading...
Searching...
No Matches
result.h
Go to the documentation of this file.
1
11#ifndef OCTANE_API_CLIENT_RESULT_H_
12#define OCTANE_API_CLIENT_RESULT_H_
13
14#include <cassert>
15#include <utility>
16
17namespace octane {
37 template <typename T_OK, typename T_Error>
38 class [[nodiscard]] Result {
39 enum struct Tag { None, OK, Error };
40 Tag tag;
41 union {
42 T_OK ok;
43 T_Error error;
44 };
45
46 template <typename T>
47 friend class ok_t;
48
49 template <typename T>
50 friend class error_t;
51
52 public:
53 Result(const Result& result) : tag(result.tag) {
54 switch (tag) {
55 case Tag::None:
56 break;
57 case Tag::OK:
58 new (&ok) T_OK(result.ok);
59 break;
60 case Tag::Error:
61 new (&error) T_Error(result.error);
62 break;
63 default:
64 std::abort();
65 }
66 }
67 Result(Result&& result) : tag(result.tag) {
68 switch (tag) {
69 case Tag::None:
70 break;
71 case Tag::OK:
72 new (&ok) T_OK(std::move(result.ok));
73 break;
74 case Tag::Error:
75 new (&error) T_Error(std::move(result.error));
76 break;
77 default:
78 std::abort();
79 }
80 result.tag = Tag::None;
81 }
83 switch (tag) {
84 case Tag::None:
85 break;
86 case Tag::OK:
87 ok.~T_OK();
88 break;
89 case Tag::Error:
90 error.~T_Error();
91 break;
92 default:
93 std::abort();
94 }
95 tag = Tag::None;
96 }
97
98 Result& operator=(const Result& result) & {
99 if (&result != this) {
100 switch (result.tag) {
101 case Tag::None:
102 this->~Result();
103 break;
104 case Tag::OK:
105 *this = result.ok();
106 break;
107 case Tag::Error:
108 *this = result.error();
109 break;
110 default:
111 std::abort();
112 }
113 }
114 return *this;
115 }
116 Result& operator=(Result&& result) & {
117 assert(this != &result);
118 switch (result.tag) {
119 case Tag::None:
120 this->~Result();
121 break;
122 case Tag::OK:
123 *this = std::move(result.ok);
124 break;
125 case Tag::Error:
126 *this = std::move(result.error);
127 break;
128 default:
129 std::abort();
130 }
131 result.tag = Tag::None;
132 return *this;
133 }
134
135 private:
136 Result(const T_OK& ok, [[maybe_unused]] int) : tag(Tag::OK), ok(ok) {}
137 Result(T_OK&& ok, [[maybe_unused]] int) : tag(Tag::OK), ok(std::move(ok)) {}
138
139 Result(const T_Error& error) : tag(Tag::Error), error(error) {}
140 Result(T_Error&& error) : tag(Tag::Error), error(std::move(error)) {}
141
142 public:
149 operator bool() const noexcept {
150 assert(tag != Tag::None);
151 return tag == Tag::OK;
152 }
159 bool operator!() const noexcept {
160 assert(tag != Tag::None);
161 return tag == Tag::Error;
162 }
171 const T_OK& get() const {
172 assert(tag == Tag::OK);
173 return ok;
174 }
183 T_OK& get() {
184 assert(tag == Tag::OK);
185 return ok;
186 }
195 const T_Error& err() const {
196 assert(tag == Tag::Error);
197 return error;
198 }
207 T_Error& err() {
208 assert(tag == Tag::Error);
209 return error;
210 }
211 };
212
222 struct _ {};
223
235 template <typename T>
236 class ok_t {
237 T ok;
238
239 public:
240 explicit ok_t(const T& ok) : ok(ok) {}
241 explicit ok_t(T&& ok) : ok(std::move(ok)) {}
242 template <typename T_OK, typename T_Error>
244 return Result<T_OK, T_Error>(std::move(ok), 0);
245 }
246 };
260 template <typename T_OK>
261 decltype(auto) ok(const T_OK& ok) {
262 return ok_t(ok);
263 }
277 template <typename T_OK>
278 decltype(auto) ok(T_OK&& ok) {
279 return ok_t(std::move(ok));
280 }
293 template <typename T_OK = _>
295 return ok(_{});
296 }
297
309 template <typename T>
310 class error_t {
311 T error;
312
313 public:
314 explicit error_t(const T& error) : error(error) {}
315 explicit error_t(T&& error) : error(std::move(error)) {}
316 template <typename T_OK, typename T_Error>
318 return Result<T_OK, T_Error>(std::move(error));
319 }
320 };
349 template <typename T_Error, size_t N>
350 decltype(auto) error(const T_Error (&error)[N]) {
351 return error_t((const T_Error*)error);
352 }
368 template <typename T_Error>
369 decltype(auto) error(const T_Error& error) {
370 return error_t(error);
371 }
387 template <typename T_Error>
388 decltype(auto) err(T_Error&& error) {
389 return error_t(std::move(error));
390 }
391} // namespace octane
392
393#endif // OCTANE_API_CLIENT_RESULT_H_
Wrapper class that bifurcates the values indicated by normal and quasi-normal states.
Definition: result.h:38
bool operator!() const noexcept
Judges whether the state is quasi-normal.
Definition: result.h:159
Result & operator=(const Result &result) &
Definition: result.h:98
T_Error error
Definition: result.h:43
T_OK ok
Definition: result.h:42
~Result()
Definition: result.h:82
Result(const Result &result)
Definition: result.h:53
Result & operator=(Result &&result) &
Definition: result.h:116
const T_OK & get() const
Get the value of normal state as a constant.
Definition: result.h:171
const T_Error & err() const
Get the value of quasi-normal state as a constant.
Definition: result.h:195
T_Error & err()
Get the value of quasi-normal state.
Definition: result.h:207
T_OK & get()
Get the value of normal state.
Definition: result.h:183
Result(Result &&result)
Definition: result.h:67
Utility class that can be used when we only want to specify quasi-normal state types.
Definition: result.h:310
error_t(T &&error)
Definition: result.h:315
error_t(const T &error)
Definition: result.h:314
Utility class that can be used when we only want to specify normal state types.
Definition: result.h:236
ok_t(const T &ok)
Definition: result.h:240
ok_t(T &&ok)
Definition: result.h:241
Definition: api_client.cpp:20
decltype(auto) error(const T_Error(&error)[N])
Utility function used to construct quasi-normal state values.
Definition: result.h:350
decltype(auto) err(T_Error &&error)
Utility function to construct quasi-normal state values.
Definition: result.h:388
decltype(auto) ok(const T_OK &ok)
Utility function used to construct normal state values.
Definition: result.h:261
ok_t< _ > ok()
Utitlity function used when the normal state type is _.
Definition: result.h:294
Structure representing that it returns nothing.
Definition: result.h:222