Console Library 8.0.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
result.h
Go to the documentation of this file.
1
10
11/*
12Copyright (c) 2026 MrXie1109
13
14Permission is hereby granted, free of charge, to any person obtaining a copy
15of this software and associated documentation files (the "Software"), to deal
16in the Software without restriction, including without limitation the rights
17to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18copies of the Software, and to permit persons to whom the Software is
19furnished to do so, subject to the following conditions:
20
21The above copyright notice and this permission notice shall be included in all
22copies or substantial portions of the Software.
23
24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30SOFTWARE.
31*/
32
33#pragma once
34#include <cassert>
35#include <cstring>
36#include <new>
37#include <type_traits>
38#include <utility>
39
40#include "../core/csexc.h"
41
42#if __cplusplus >= 201703L
43#include <optional>
44#endif
45
46namespace console {
56 template <class T, class E>
57 class Result {
58 static_assert(
59 !std::is_same<T, E>::value, "T and E cannot be the same type");
60
62 static constexpr size_t buffer_size
63 = sizeof(T) > sizeof(E) ? sizeof(T) : sizeof(E);
65 static constexpr size_t buffer_align
66 = alignof(T) > alignof(E) ? alignof(T) : alignof(E);
67
69 alignas(buffer_align) mutable unsigned char buffer[buffer_size];
71 bool is_ok_;
72
74 T *get_ok_ptr() const { return reinterpret_cast<T *>(buffer); }
76 E *get_err_ptr() const { return reinterpret_cast<E *>(buffer); }
77
78 public:
80 typedef T value_type;
82 typedef E error_type;
83
88 Result(const T &value) : is_ok_(true) { new (get_ok_ptr()) T(value); }
89
94 Result(const E &error) : is_ok_(false) { new (get_err_ptr()) E(error); }
95
100 Result(T &&value) : is_ok_(true) {
101 new (get_ok_ptr()) T(std::move(value));
102 }
103
108 Result(E &&error) : is_ok_(false) {
109 new (get_err_ptr()) E(std::move(error));
110 }
111
117 Result(const Result &other) : is_ok_(other.is_ok_) {
118 if (is_ok_) {
119 new (get_ok_ptr()) T(*other.get_ok_ptr());
120 } else {
121 new (get_err_ptr()) E(*other.get_err_ptr());
122 }
123 }
124
129 Result(Result &&other) noexcept : is_ok_(other.is_ok_) {
130 if (is_ok_)
131 new (get_ok_ptr()) T(std::move(*other.get_ok_ptr()));
132 else
133 new (get_err_ptr()) E(std::move(*other.get_err_ptr()));
134 }
135
141 Result &operator=(const Result &other) {
142 if (this != &other) Result(other).swap(*this);
143 return *this;
144 }
145
151 Result &operator=(Result &&other) noexcept {
152 if (this != &other) Result(std::move(other)).swap(*this);
153 return *this;
154 }
155
160 if (is_ok_)
161 get_ok_ptr()->~T();
162 else
163 get_err_ptr()->~E();
164 }
165
172 T ok() const & {
173 assert(is_ok_ && "Called get_ok on error");
174 return *get_ok_ptr();
175 }
176
183 E err() const & {
184 assert(!is_ok_ && "Called get_err on success");
185 return *get_err_ptr();
186 }
187
194 T ok() && {
195 assert(is_ok_ && "Called get_ok on error");
196 return std::move(*get_ok_ptr());
197 }
198
205 E err() && {
206 assert(!is_ok_ && "Called get_err on success");
207 return std::move(*get_err_ptr());
208 }
209
216 T unwrap() const {
217 if (!is_ok_) throw ValueError("Called unwrap on error");
218 return *get_ok_ptr();
219 }
220
228 T expect(const std::string &msg) const {
229 if (!is_ok_) throw ValueError(msg);
230 return *get_ok_ptr();
231 }
232
237 bool is_ok() const { return is_ok_; }
238
243 bool is_err() const { return !is_ok_; }
244
253 template <class F, class G>
254 void visit(F &&f, G &&g) const {
255 if (is_ok_)
256 f(ok());
257 else
258 g(err());
259 }
260
267 template <class F>
268 auto and_then(F &&f) const & -> Result< //
269 typename std::decay<decltype(f(
270 std::declval<T>()))>::type::value_type,
271 E> {
272 if (is_ok_) return f(*get_ok_ptr());
273 return *get_err_ptr();
274 }
275
282 template <class F>
283 auto and_then(F &&f) && -> Result< //
284 typename std::decay<decltype(f(
285 std::declval<T>()))>::type::value_type,
286 E> {
287 if (is_ok_) return f(std::move(*get_ok_ptr()));
288 return std::move(*get_err_ptr());
289 }
290
298 template <class F>
299 auto or_else(F &&f) const & -> Result<T,
300 typename std::decay<decltype(f(
301 std::declval<E>()))>::type::error_type> {
302 if (is_ok_) return ok();
303 return f(err());
304 }
305
313 template <class F>
314 auto or_else(F &&f) && -> Result<T,
315 typename std::decay<decltype(f(
316 std::declval<E>()))>::type::error_type> {
317 if (is_ok_) return std::move(*get_ok_ptr());
318 return f(std::move(*get_err_ptr()));
319 }
320
325 void swap(Result &other) noexcept {
326 if (this == &other) return;
327 if (is_ok_ && other.is_ok_) {
328 T temp = std::move(*get_ok_ptr());
329 *get_ok_ptr() = std::move(*other.get_ok_ptr());
330 *other.get_ok_ptr() = std::move(temp);
331 } else if (!is_ok_ && !other.is_ok_) {
332 E temp = std::move(*get_err_ptr());
333 *get_err_ptr() = std::move(*other.get_err_ptr());
334 *other.get_err_ptr() = std::move(temp);
335 } else if (is_ok_) {
336 T temp_t = std::move(*get_ok_ptr());
337 get_ok_ptr()->~T();
338 new (get_err_ptr()) E(std::move(*other.get_err_ptr()));
339 other.get_err_ptr()->~E();
340 new (other.get_ok_ptr()) T(std::move(temp_t));
341 } else {
342 E temp_e = std::move(*get_err_ptr());
343 get_err_ptr()->~E();
344 new (get_ok_ptr()) T(std::move(*other.get_ok_ptr()));
345 other.get_ok_ptr()->~T();
346 new (other.get_err_ptr()) E(std::move(temp_e));
347 }
348 std::swap(is_ok_, other.is_ok_);
349 }
350
356 friend void swap(Result &a, Result &b) noexcept { a.swap(b); }
357
362 explicit operator bool() const { return is_ok_; }
363
368 bool operator!() const { return !is_ok_; }
369
375 const T &unwrap_or(const T &default_value) const & {
376 return is_ok_ ? *get_ok_ptr() : default_value;
377 }
378
384 T unwrap_or(T &&default_value) && {
385 return is_ok_ ? std::move(*get_ok_ptr()) : std::move(default_value);
386 }
387
393 template <class F>
394 T unwrap_or_else(F &&fn) const & {
395 return is_ok_ ? *get_ok_ptr() : fn();
396 }
397
403 template <class F>
404 T unwrap_or_else(F &&fn) && {
405 return is_ok_ ? std::move(*get_ok_ptr()) : fn();
406 }
407
412 const T *ok_ptr() const { return is_ok_ ? get_ok_ptr() : nullptr; }
413
418 T *ok_ptr() { return is_ok_ ? get_ok_ptr() : nullptr; }
419
424 const E *err_ptr() const { return !is_ok_ ? get_err_ptr() : nullptr; }
425
430 E *err_ptr() { return !is_ok_ ? get_err_ptr() : nullptr; }
431
436 bool operator==(const Result &other) const {
437 if (is_ok_ != other.is_ok_) return false;
438 if (is_ok_) return *get_ok_ptr() == *other.get_ok_ptr();
439 return *get_err_ptr() == *other.get_err_ptr();
440 }
441
446 bool operator!=(const Result &other) const { return !(*this == other); }
447
448#if __cplusplus >= 201703L
454 std::optional<T> as_optional() const & {
455 return is_ok_ ? std::optional<T>(*get_ok_ptr()) : std::nullopt;
456 }
457
463 std::optional<T> as_optional() && {
464 return is_ok_ ? std::optional<T>(std::move(*get_ok_ptr()))
465 : std::nullopt;
466 }
467#endif
468 };
469
474}
T unwrap_or_else(F &&fn) const &
如果是Ok则返回Ok值,否则通过函数生成默认值。
Definition result.h:394
static constexpr size_t buffer_align
缓冲区对齐要求,取 T 和 E 中较大者。
Definition result.h:66
T unwrap_or_else(F &&fn) &&
如果是Ok则移动返回值,否则通过函数生成默认值。
Definition result.h:404
const E * err_ptr() const
获取Err值的指针(可能为空)。
Definition result.h:424
T unwrap() const
解包成功值,若为错误则抛出异常。
Definition result.h:216
static constexpr size_t buffer_size
缓冲区大小,取 T 和 E 中较大者。
Definition result.h:63
T expect(const std::string &msg) const
带自定义消息的解包,若为错误则抛出异常。
Definition result.h:228
E * err_ptr()
获取Err值的指针(可能为空)。
Definition result.h:430
void visit(F &&f, G &&g) const
访问 Result 的内容,根据状态调用不同的函数。
Definition result.h:254
bool operator==(const Result &other) const
相等性比较。
Definition result.h:436
T unwrap_or(T &&default_value) &&
如果是Ok则移动返回值,否则返回默认值。
Definition result.h:384
T ok() &&
移动获取成功值(右值引用版本)。
Definition result.h:194
auto or_else(F &&f) const &-> Result< T, typename std::decay< decltype(f(std::declval< E >()))>::type::error_type >
链式操作:若为 Err 则应用 f,否则传递 Ok(左值引用版本)。
Definition result.h:299
T * ok_ptr()
获取Ok值的指针(可能为空)。
Definition result.h:418
~Result()
析构函数,正确销毁当前存储的值。
Definition result.h:159
Result(const E &error)
从错误值构造 Result(拷贝)。
Definition result.h:94
Result & operator=(const Result &other)
拷贝赋值(使用 copy-and-swap 惯用法)。
Definition result.h:141
T value_type
成功值类型别名。
Definition result.h:80
const T & unwrap_or(const T &default_value) const &
如果是Ok则返回值的引用,否则返回默认值的引用。
Definition result.h:375
unsigned char buffer[buffer_size]
对齐的原始字节缓冲区,用于存储 T 或 E。
Definition result.h:69
friend void swap(Result &a, Result &b) noexcept
交换两个 Result 的内容(友元函数)。
Definition result.h:356
Result(T &&value)
从成功值构造 Result(移动)。
Definition result.h:100
const T * ok_ptr() const
获取Ok值的指针(可能为空)。
Definition result.h:412
E * get_err_ptr() const
获取指向错误值 E 的指针(常量)。
Definition result.h:76
T ok() const &
获取成功值的副本(左值引用版本)。
Definition result.h:172
auto and_then(F &&f) const &-> Result< typename std::decay< decltype(f(std::declval< T >()))>::type::value_type, E >
链式操作:若为 Ok 则应用 f,否则传递 Err(左值引用版本)。
Definition result.h:268
T * get_ok_ptr() const
获取指向成功值 T 的指针(常量)。
Definition result.h:74
void swap(Result &other) noexcept
交换两个 Result 的内容。
Definition result.h:325
Result(Result &&other) noexcept
移动构造,转移内部值。
Definition result.h:129
Result(const Result &other)
拷贝构造,深拷贝内部值。
Definition result.h:117
bool is_ok_
标记当前是否为 Ok 状态(true 表示 Ok,false 表示 Err)。
Definition result.h:71
E err() const &
获取错误值的副本(左值引用版本)。
Definition result.h:183
E err() &&
移动获取错误值(右值引用版本)。
Definition result.h:205
Result & operator=(Result &&other) noexcept
移动赋值(使用 copy-and-swap 惯用法)。
Definition result.h:151
bool is_ok() const
检查是否为 Ok(成功)状态。
Definition result.h:237
bool operator!() const
逻辑非,检查是否为 Err。
Definition result.h:368
bool operator!=(const Result &other) const
不等性比较。
Definition result.h:446
bool is_err() const
检查是否为 Err(错误)状态。
Definition result.h:243
Result(const T &value)
从成功值构造 Result(拷贝)。
Definition result.h:88
E error_type
错误值类型别名。
Definition result.h:82
auto or_else(F &&f) &&-> Result< T, typename std::decay< decltype(f(std::declval< E >()))>::type::error_type >
链式操作:若为 Err 则应用 f,否则传递 Ok(右值引用版本)。
Definition result.h:314
auto and_then(F &&f) &&-> Result< typename std::decay< decltype(f(std::declval< T >()))>::type::value_type, E >
链式操作:若为 Ok 则应用 f,否则传递 Err(右值引用版本)。
Definition result.h:283
Result(E &&error)
从错误值构造 Result(移动)。
Definition result.h:108
ValueError(const std::string &msg)
构造 ValueError。
Definition csexc.h:115
定义 console 库使用的自定义异常类层次结构。
本库所有组件所在的顶层命名空间。
@ E
Definition kb.h:84
@ T
Definition kb.h:99