diff options
Diffstat (limited to 'kernel/lib/libcxx/include/__expected/expected.h')
| -rw-r--r-- | kernel/lib/libcxx/include/__expected/expected.h | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/kernel/lib/libcxx/include/__expected/expected.h b/kernel/lib/libcxx/include/__expected/expected.h new file mode 100644 index 0000000..2266cd2 --- /dev/null +++ b/kernel/lib/libcxx/include/__expected/expected.h @@ -0,0 +1,403 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the BastionOS freestanding C++ standard library. +// +// std::expected (C++23) — no-exceptions version (traps on bad access). +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBBASTION_EXPECTED_EXPECTED_H +#define _LIBBASTION_EXPECTED_EXPECTED_H + +#include <__config> +#include <__type_traits/construction_traits.h> +#include <__type_traits/type_modifications.h> +#include <__type_traits/type_relationships.h> +#include <__utility/move.h> +#include <__utility/swap.h> +#include <__utility/in_place.h> +#include <new> + +_LIBBASTION_BEGIN_NAMESPACE_STD + +// ── unexpect tag ──────────────────────────────────────────────────────────── + +struct unexpect_t { explicit unexpect_t() = default; }; +inline constexpr unexpect_t unexpect{}; + +// ── unexpected ────────────────────────────────���──────────────────────────���── + +template<class _Err> +class unexpected { + static_assert(!__is_void(_Err), "unexpected<void> is ill-formed"); +public: + constexpr unexpected(const unexpected&) = default; + constexpr unexpected(unexpected&&) = default; + + template<class _Er = _Err> + requires (!__is_same(__decay(_Er), unexpected)) && (!__is_same(__decay(_Er), in_place_t)) && + is_constructible_v<_Err, _Er> + constexpr explicit unexpected(_Er&& __e) : __val_(std::forward<_Er>(__e)) {} + + template<class... _Args> + requires is_constructible_v<_Err, _Args...> + constexpr explicit unexpected(in_place_t, _Args&&... __args) : __val_(std::forward<_Args>(__args)...) {} + + _LIBBASTION_NODISCARD constexpr _Err& error() & noexcept { return __val_; } + _LIBBASTION_NODISCARD constexpr const _Err& error() const& noexcept { return __val_; } + _LIBBASTION_NODISCARD constexpr _Err&& error() && noexcept { return std::move(__val_); } + _LIBBASTION_NODISCARD constexpr const _Err&& error() const&& noexcept { return std::move(__val_); } + + template<class _Er2> + _LIBBASTION_NODISCARD friend constexpr bool operator==(const unexpected& __x, const unexpected<_Er2>& __y) { + return __x.error() == __y.error(); + } + + constexpr void swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Err>) { + using std::swap; + swap(__val_, __other.__val_); + } + +private: + _Err __val_; +}; + +template<class _Err> +unexpected(_Err) -> unexpected<_Err>; + +// ── expected<T, E> ───────────────────────────��────────────────────────────── + +template<class _Tp, class _Err> +class expected { + static_assert(!__is_void(_Err), "expected<T, void> is ill-formed; use expected<void, E> for void value"); + static_assert(!__is_reference(_Tp), "expected<T&, E> is ill-formed"); + static_assert(!__is_reference(_Err), "expected<T, E&> is ill-formed"); + +public: + using value_type = _Tp; + using error_type = _Err; + using unexpected_type = unexpected<_Err>; + + // ── Constructors ──────────────────────────��───────────────────────── + + constexpr expected() + noexcept(is_nothrow_default_constructible_v<_Tp>) + requires is_default_constructible_v<_Tp> + : __has_val_(true) + { ::new (static_cast<void*>(&__val_)) _Tp(); } + + constexpr expected(const expected& __other) + requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> + : __has_val_(__other.__has_val_) + { + if (__has_val_) ::new (static_cast<void*>(&__val_)) _Tp(__other.__val_); + else ::new (static_cast<void*>(&__err_)) _Err(__other.__err_); + } + + constexpr expected(expected&& __other) + noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>) + requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> + : __has_val_(__other.__has_val_) + { + if (__has_val_) ::new (static_cast<void*>(&__val_)) _Tp(std::move(__other.__val_)); + else ::new (static_cast<void*>(&__err_)) _Err(std::move(__other.__err_)); + } + + template<class _Up = _Tp> + requires (!__is_same(__decay(_Up), expected)) && + (!__is_same(__decay(_Up), in_place_t)) && + is_constructible_v<_Tp, _Up> + constexpr expected(_Up&& __val) : __has_val_(true) { + ::new (static_cast<void*>(&__val_)) _Tp(std::forward<_Up>(__val)); + } + + template<class _G> + requires is_constructible_v<_Err, const _G&> + constexpr expected(const unexpected<_G>& __e) : __has_val_(false) { + ::new (static_cast<void*>(&__err_)) _Err(__e.error()); + } + + template<class _G> + requires is_constructible_v<_Err, _G> + constexpr expected(unexpected<_G>&& __e) : __has_val_(false) { + ::new (static_cast<void*>(&__err_)) _Err(std::move(__e.error())); + } + + template<class... _Args> + requires is_constructible_v<_Tp, _Args...> + constexpr explicit expected(in_place_t, _Args&&... __args) : __has_val_(true) { + ::new (static_cast<void*>(&__val_)) _Tp(std::forward<_Args>(__args)...); + } + + template<class... _Args> + requires is_constructible_v<_Err, _Args...> + constexpr explicit expected(unexpect_t, _Args&&... __args) : __has_val_(false) { + ::new (static_cast<void*>(&__err_)) _Err(std::forward<_Args>(__args)...); + } + + // ── Destructor ───────────────────────��────────────────────────────── + + constexpr ~expected() + requires is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err> + = default; + + constexpr ~expected() + requires (!(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)) + { + if (__has_val_) __val_.~_Tp(); + else __err_.~_Err(); + } + + // ── Assignment ───────���───────────────────────────���────────────────── + + constexpr expected& operator=(const expected& __other) + requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && + is_copy_assignable_v<_Tp> && is_copy_assignable_v<_Err> + { + if (__has_val_ && __other.__has_val_) { + __val_ = __other.__val_; + } else if (!__has_val_ && !__other.__has_val_) { + __err_ = __other.__err_; + } else { + __destroy(); + __has_val_ = __other.__has_val_; + if (__has_val_) ::new (static_cast<void*>(&__val_)) _Tp(__other.__val_); + else ::new (static_cast<void*>(&__err_)) _Err(__other.__err_); + } + return *this; + } + + constexpr expected& operator=(expected&& __other) + noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>) + requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && + is_move_assignable_v<_Tp> && is_move_assignable_v<_Err> + { + if (__has_val_ && __other.__has_val_) { + __val_ = std::move(__other.__val_); + } else if (!__has_val_ && !__other.__has_val_) { + __err_ = std::move(__other.__err_); + } else { + __destroy(); + __has_val_ = __other.__has_val_; + if (__has_val_) ::new (static_cast<void*>(&__val_)) _Tp(std::move(__other.__val_)); + else ::new (static_cast<void*>(&__err_)) _Err(std::move(__other.__err_)); + } + return *this; + } + + // ── Observers ─────────────────────────────────────────────────────── + + _LIBBASTION_NODISCARD constexpr bool has_value() const noexcept { return __has_val_; } + _LIBBASTION_NODISCARD constexpr explicit operator bool() const noexcept { return __has_val_; } + + _LIBBASTION_NODISCARD constexpr _Tp& operator*() & { return __val_; } + _LIBBASTION_NODISCARD constexpr const _Tp& operator*() const& { return __val_; } + _LIBBASTION_NODISCARD constexpr _Tp&& operator*() && { return std::move(__val_); } + _LIBBASTION_NODISCARD constexpr _Tp* operator->() { return &__val_; } + _LIBBASTION_NODISCARD constexpr const _Tp* operator->() const { return &__val_; } + + _LIBBASTION_NODISCARD constexpr _Tp& value() & { + if (!__has_val_) _LIBBASTION_TRAP(); + return __val_; + } + _LIBBASTION_NODISCARD constexpr const _Tp& value() const& { + if (!__has_val_) _LIBBASTION_TRAP(); + return __val_; + } + _LIBBASTION_NODISCARD constexpr _Tp&& value() && { + if (!__has_val_) _LIBBASTION_TRAP(); + return std::move(__val_); + } + + _LIBBASTION_NODISCARD constexpr _Err& error() & { return __err_; } + _LIBBASTION_NODISCARD constexpr const _Err& error() const& { return __err_; } + _LIBBASTION_NODISCARD constexpr _Err&& error() && { return std::move(__err_); } + + template<class _Up> + _LIBBASTION_NODISCARD constexpr _Tp value_or(_Up&& __default_val) const& { + return __has_val_ ? __val_ : static_cast<_Tp>(std::forward<_Up>(__default_val)); + } + template<class _Up> + _LIBBASTION_NODISCARD constexpr _Tp value_or(_Up&& __default_val) && { + return __has_val_ ? std::move(__val_) : static_cast<_Tp>(std::forward<_Up>(__default_val)); + } + + // ── Monadic operations (C++23) ───────────────────────��────────────── + + template<class _Fn> + constexpr auto and_then(_Fn&& __f) & { + if (__has_val_) return std::forward<_Fn>(__f)(__val_); + using _Result = __decay(decltype(std::forward<_Fn>(__f)(__val_))); + return _Result(unexpect, __err_); + } + + template<class _Fn> + constexpr auto and_then(_Fn&& __f) const& { + if (__has_val_) return std::forward<_Fn>(__f)(__val_); + using _Result = __decay(decltype(std::forward<_Fn>(__f)(__val_))); + return _Result(unexpect, __err_); + } + + template<class _Fn> + constexpr auto and_then(_Fn&& __f) && { + if (__has_val_) return std::forward<_Fn>(__f)(std::move(__val_)); + using _Result = __decay(decltype(std::forward<_Fn>(__f)(std::move(__val_)))); + return _Result(unexpect, std::move(__err_)); + } + + template<class _Fn> + constexpr auto transform(_Fn&& __f) & { + using _Up = __remove_cvref(decltype(std::forward<_Fn>(__f)(__val_))); + if (__has_val_) return expected<_Up, _Err>(std::forward<_Fn>(__f)(__val_)); + return expected<_Up, _Err>(unexpect, __err_); + } + + template<class _Fn> + constexpr auto transform(_Fn&& __f) const& { + using _Up = __remove_cvref(decltype(std::forward<_Fn>(__f)(__val_))); + if (__has_val_) return expected<_Up, _Err>(std::forward<_Fn>(__f)(__val_)); + return expected<_Up, _Err>(unexpect, __err_); + } + + template<class _Fn> + constexpr auto or_else(_Fn&& __f) & { + if (__has_val_) { + using _Result = __decay(decltype(std::forward<_Fn>(__f)(__err_))); + return _Result(__val_); + } + return std::forward<_Fn>(__f)(__err_); + } + + template<class _Fn> + constexpr auto or_else(_Fn&& __f) const& { + if (__has_val_) { + using _Result = __decay(decltype(std::forward<_Fn>(__f)(__err_))); + return _Result(__val_); + } + return std::forward<_Fn>(__f)(__err_); + } + + template<class _Fn> + constexpr auto transform_error(_Fn&& __f) & { + using _G = __remove_cvref(decltype(std::forward<_Fn>(__f)(__err_))); + if (__has_val_) return expected<_Tp, _G>(in_place, __val_); + return expected<_Tp, _G>(unexpect, std::forward<_Fn>(__f)(__err_)); + } + + template<class _Fn> + constexpr auto transform_error(_Fn&& __f) const& { + using _G = __remove_cvref(decltype(std::forward<_Fn>(__f)(__err_))); + if (__has_val_) return expected<_Tp, _G>(in_place, __val_); + return expected<_Tp, _G>(unexpect, std::forward<_Fn>(__f)(__err_)); + } + + // ── Modifiers ─────────────────────────────────────────────────────── + + template<class... _Args> + constexpr _Tp& emplace(_Args&&... __args) { + __destroy(); + ::new (static_cast<void*>(&__val_)) _Tp(std::forward<_Args>(__args)...); + __has_val_ = true; + return __val_; + } + +private: + constexpr void __destroy() { + if (__has_val_) { + if constexpr (!is_trivially_destructible_v<_Tp>) __val_.~_Tp(); + } else { + if constexpr (!is_trivially_destructible_v<_Err>) __err_.~_Err(); + } + } + + union { + _Tp __val_; + _Err __err_; + }; + bool __has_val_; +}; + +// ── expected<void, E> specialization ──────────────────────────────────────── + +template<class _Err> +class expected<void, _Err> { +public: + using value_type = void; + using error_type = _Err; + using unexpected_type = unexpected<_Err>; + + constexpr expected() noexcept : __has_val_(true) {} + + template<class _G> + requires is_constructible_v<_Err, const _G&> + constexpr expected(const unexpected<_G>& __e) : __has_val_(false) { + ::new (static_cast<void*>(&__err_)) _Err(__e.error()); + } + + template<class _G> + requires is_constructible_v<_Err, _G> + constexpr expected(unexpected<_G>&& __e) : __has_val_(false) { + ::new (static_cast<void*>(&__err_)) _Err(std::move(__e.error())); + } + + constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {} + + template<class... _Args> + requires is_constructible_v<_Err, _Args...> + constexpr explicit expected(unexpect_t, _Args&&... __args) : __has_val_(false) { + ::new (static_cast<void*>(&__err_)) _Err(std::forward<_Args>(__args)...); + } + + constexpr ~expected() requires is_trivially_destructible_v<_Err> = default; + constexpr ~expected() requires (!is_trivially_destructible_v<_Err>) { + if (!__has_val_) __err_.~_Err(); + } + + _LIBBASTION_NODISCARD constexpr bool has_value() const noexcept { return __has_val_; } + _LIBBASTION_NODISCARD constexpr explicit operator bool() const noexcept { return __has_val_; } + + constexpr void operator*() const noexcept {} + constexpr void value() const { if (!__has_val_) _LIBBASTION_TRAP(); } + + _LIBBASTION_NODISCARD constexpr _Err& error() & { return __err_; } + _LIBBASTION_NODISCARD constexpr const _Err& error() const& { return __err_; } + _LIBBASTION_NODISCARD constexpr _Err&& error() && { return std::move(__err_); } + + constexpr void emplace() noexcept { + if (!__has_val_) { + if constexpr (!is_trivially_destructible_v<_Err>) __err_.~_Err(); + __has_val_ = true; + } + } + +private: + union { + char __empty_; + _Err __err_; + }; + bool __has_val_; +}; + +// ── Comparison ────────────────────────────────────────────────────────────── + +template<class _T1, class _E1, class _T2, class _E2> +_LIBBASTION_NODISCARD constexpr bool operator==(const expected<_T1, _E1>& __x, const expected<_T2, _E2>& __y) { + if (__x.has_value() != __y.has_value()) return false; + if (__x.has_value()) return *__x == *__y; + return __x.error() == __y.error(); +} + +template<class _T1, class _E1, class _T2> +_LIBBASTION_NODISCARD constexpr bool operator==(const expected<_T1, _E1>& __x, const _T2& __y) { + return __x.has_value() && *__x == __y; +} + +template<class _T1, class _E1, class _E2> +_LIBBASTION_NODISCARD constexpr bool operator==(const expected<_T1, _E1>& __x, const unexpected<_E2>& __y) { + return !__x.has_value() && __x.error() == __y.error(); +} + +_LIBBASTION_END_NAMESPACE_STD + +#endif // _LIBBASTION_EXPECTED_EXPECTED_H |
