diff options
Diffstat (limited to 'asl/status_or.hpp')
-rw-r--r-- | asl/status_or.hpp | 358 |
1 files changed, 179 insertions, 179 deletions
diff --git a/asl/status_or.hpp b/asl/status_or.hpp index b8b2881..cb65147 100644 --- a/asl/status_or.hpp +++ b/asl/status_or.hpp @@ -1,179 +1,179 @@ -#pragma once
-
-#include "asl/status.hpp"
-#include "asl/maybe_uninit.hpp"
-#include "asl/hash.hpp"
-
-namespace asl
-{
-
-template<is_object T>
-class status_or
-{
- status m_status;
- maybe_uninit<T> m_value{};
-
-public:
- // @Todo Convert copy
- // @Todo Convert move
-
- constexpr status_or(const status_or& other)
- requires copy_constructible<T>
- : m_status{other.m_status}
- {
- if (other.ok())
- {
- m_value.construct_unsafe(other.m_value.as_init_unsafe());
- }
- }
-
- constexpr status_or(status_or&& other)
- requires move_constructible<T>
- : m_status{ASL_MOVE(other.m_status)}
- {
- if (other.ok())
- {
- m_value.construct_unsafe(ASL_MOVE(other.m_value.as_init_unsafe()));
- }
- }
-
- constexpr status_or& operator=(const status_or& other)
- requires copyable<T>
- {
- if (&other != this)
- {
- if (ok())
- {
- if (other.ok())
- {
- m_value.assign_unsafe(other.m_value.as_init_unsafe());
- }
- else
- {
- m_value.destroy_unsafe();
- }
- }
- else if (other.ok())
- {
- m_value.construct_unsafe(other.m_value.as_init_unsafe());
- }
- m_status = other.m_status;
- }
- return *this;
- }
-
- constexpr status_or& operator=(status_or&& other)
- requires moveable<T>
- {
- if (&other != this)
- {
- if (ok())
- {
- if (other.ok())
- {
- m_value.assign_unsafe(ASL_MOVE(other.m_value.as_init_unsafe()));
- }
- else
- {
- m_value.destroy_unsafe();
- }
- }
- else if (other.ok())
- {
- m_value.construct_unsafe(ASL_MOVE(other.m_value.as_init_unsafe()));
- }
- m_status = ASL_MOVE(other.m_status);
- }
- return *this;
- }
-
- constexpr ~status_or()
- {
- if (m_status.ok())
- {
- m_value.destroy_unsafe();
- }
- }
-
- // NOLINTNEXTLINE(*-explicit-conversions)
- constexpr status_or(const status& status) : m_status{status}
- {
- ASL_ASSERT_RELEASE(!m_status.ok());
- }
-
- // NOLINTNEXTLINE(*-explicit-conversions)
- constexpr status_or(status&& status) : m_status{ASL_MOVE(status)}
- {
- ASL_ASSERT_RELEASE(!m_status.ok());
- }
-
- status_or& operator=(status status) = delete;
-
- template<typename U = T>
- constexpr explicit (!convertible_from<T, U&&>)
- status_or(U&& value)
- requires (
- constructible_from<T, U&&> &&
- !same_as<un_cvref_t<U>, status_or> &&
- !same_as<un_cvref_t<U>, status>
- )
- : m_status{status_code::ok}
- , m_value{in_place, ASL_FWD(value)}
- {}
-
- constexpr bool ok() const { return m_status.ok(); }
-
- constexpr status_code code() const { return m_status.code(); }
-
- constexpr string_view message() const { return m_status.message(); }
-
- // @Todo(C++23) Deducing this
- constexpr const T& value() const&
- {
- ASL_ASSERT_RELEASE(ok());
- return m_value.as_init_unsafe();
- }
-
- constexpr T& value() &
- {
- ASL_ASSERT_RELEASE(ok());
- return m_value.as_init_unsafe();
- }
-
- constexpr T&& value() &&
- {
- ASL_ASSERT_RELEASE(ok());
- return ASL_MOVE(m_value.as_init_unsafe());
- }
-
- template<typename U>
- constexpr T value_or(U&& other_value) const&
- requires copy_constructible<T> && convertible_from<T, U&&>
- {
- return ok() ? value() : static_cast<T>(ASL_FWD(other_value));
- }
-
- template<typename U>
- constexpr T value_or(U&& other_value) &&
- requires move_constructible<T> && convertible_from<T, U&&>
- {
- return ok() ? ASL_MOVE(value()) : static_cast<T>(ASL_FWD(other_value));
- }
-
- template<typename H>
- requires hashable<T>
- friend H AslHashValue(H h, const status_or& s)
- {
- if (s.ok())
- {
- return H::combine(ASL_MOVE(h), s.m_status, s.value());
- }
- return H::combine(ASL_MOVE(h), s.m_status);
- }
-};
-
-template<typename T>
-status_or(T) -> status_or<T>;
-
-} // namespace asl
-
+#pragma once + +#include "asl/status.hpp" +#include "asl/maybe_uninit.hpp" +#include "asl/hash.hpp" + +namespace asl +{ + +template<is_object T> +class status_or +{ + status m_status; + maybe_uninit<T> m_value{}; + +public: + // @Todo Convert copy + // @Todo Convert move + + constexpr status_or(const status_or& other) + requires copy_constructible<T> + : m_status{other.m_status} + { + if (other.ok()) + { + m_value.construct_unsafe(other.m_value.as_init_unsafe()); + } + } + + constexpr status_or(status_or&& other) + requires move_constructible<T> + : m_status{ASL_MOVE(other.m_status)} + { + if (other.ok()) + { + m_value.construct_unsafe(ASL_MOVE(other.m_value.as_init_unsafe())); + } + } + + constexpr status_or& operator=(const status_or& other) + requires copyable<T> + { + if (&other != this) + { + if (ok()) + { + if (other.ok()) + { + m_value.assign_unsafe(other.m_value.as_init_unsafe()); + } + else + { + m_value.destroy_unsafe(); + } + } + else if (other.ok()) + { + m_value.construct_unsafe(other.m_value.as_init_unsafe()); + } + m_status = other.m_status; + } + return *this; + } + + constexpr status_or& operator=(status_or&& other) + requires moveable<T> + { + if (&other != this) + { + if (ok()) + { + if (other.ok()) + { + m_value.assign_unsafe(ASL_MOVE(other.m_value.as_init_unsafe())); + } + else + { + m_value.destroy_unsafe(); + } + } + else if (other.ok()) + { + m_value.construct_unsafe(ASL_MOVE(other.m_value.as_init_unsafe())); + } + m_status = ASL_MOVE(other.m_status); + } + return *this; + } + + constexpr ~status_or() + { + if (m_status.ok()) + { + m_value.destroy_unsafe(); + } + } + + // NOLINTNEXTLINE(*-explicit-conversions) + constexpr status_or(const status& status) : m_status{status} + { + ASL_ASSERT_RELEASE(!m_status.ok()); + } + + // NOLINTNEXTLINE(*-explicit-conversions) + constexpr status_or(status&& status) : m_status{ASL_MOVE(status)} + { + ASL_ASSERT_RELEASE(!m_status.ok()); + } + + status_or& operator=(status status) = delete; + + template<typename U = T> + constexpr explicit (!convertible_from<T, U&&>) + status_or(U&& value) + requires ( + constructible_from<T, U&&> && + !same_as<un_cvref_t<U>, status_or> && + !same_as<un_cvref_t<U>, status> + ) + : m_status{status_code::ok} + , m_value{in_place, ASL_FWD(value)} + {} + + constexpr bool ok() const { return m_status.ok(); } + + constexpr status_code code() const { return m_status.code(); } + + constexpr string_view message() const { return m_status.message(); } + + // @Todo(C++23) Deducing this + constexpr const T& value() const& + { + ASL_ASSERT_RELEASE(ok()); + return m_value.as_init_unsafe(); + } + + constexpr T& value() & + { + ASL_ASSERT_RELEASE(ok()); + return m_value.as_init_unsafe(); + } + + constexpr T&& value() && + { + ASL_ASSERT_RELEASE(ok()); + return ASL_MOVE(m_value.as_init_unsafe()); + } + + template<typename U> + constexpr T value_or(U&& other_value) const& + requires copy_constructible<T> && convertible_from<T, U&&> + { + return ok() ? value() : static_cast<T>(ASL_FWD(other_value)); + } + + template<typename U> + constexpr T value_or(U&& other_value) && + requires move_constructible<T> && convertible_from<T, U&&> + { + return ok() ? ASL_MOVE(value()) : static_cast<T>(ASL_FWD(other_value)); + } + + template<typename H> + requires hashable<T> + friend H AslHashValue(H h, const status_or& s) + { + if (s.ok()) + { + return H::combine(ASL_MOVE(h), s.m_status, s.value()); + } + return H::combine(ASL_MOVE(h), s.m_status); + } +}; + +template<typename T> +status_or(T) -> status_or<T>; + +} // namespace asl + |