From 08eece258ceff7824250454906bff013a7303c28 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Wed, 24 Apr 2024 23:13:42 +0200 Subject: Some work on StatusOr --- deimos/core/status.h | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++- deimos/core/std.h | 5 ++ 2 files changed, 137 insertions(+), 2 deletions(-) (limited to 'deimos') diff --git a/deimos/core/status.h b/deimos/core/status.h index 6601ad7..912d4c8 100644 --- a/deimos/core/status.h +++ b/deimos/core/status.h @@ -46,7 +46,7 @@ public: Ref(); } - Status(Status&& other) : m_rep{std::exchange(other.m_rep, 0U)} {} + Status(Status&& other) : m_rep{std::exchange(other.m_rep, CodeToRep(StatusCode::kOk))} {} Status& operator=(const Status& other) { @@ -64,7 +64,7 @@ public: if (this != &other) { Unref(); - this->m_rep = std::exchange(other.m_rep, 0U); + this->m_rep = std::exchange(other.m_rep, CodeToRep(StatusCode::kOk)); } return *this; @@ -106,5 +106,135 @@ inline Status InternalError(StringView message = {}) return Status(StatusCode::kInternal, message); } +namespace statusor_internals +{ +}; + +template +class StatusOr +{ + deimos_StaticAssert(!std::is_constructible_v); + + struct Dummy{}; + + Status m_status; + + union { + Dummy m_dummy; + T m_value; + }; + + void Clear() + { + if constexpr (!std::is_trivially_destructible_v) + { + if (m_status.ok()) + { + (&m_value)->~T(); + } + } + } + +public: + explicit StatusOr() requires std::is_default_constructible_v : + m_value{} + {} + + template + StatusOr(Args&&... args) requires std::is_constructible_v : // NOLINT + m_value{std::forward(args)...} + {} + + StatusOr(const Status& status) : m_status{status} // NOLINT + { + if (m_status.ok()) + { + deimos_Panic("Cannot construct a StatusOr from OK"); + m_status = InternalError("StatusOr constructed from OK"); + } + } + + StatusOr(Status&& status) : m_status{std::move(status)} // NOLINT + { + if (m_status.ok()) + { + deimos_Panic("Cannot construct a StatusOr from OK"); + m_status = InternalError("StatusOr constructed from OK"); + } + } + + StatusOr(const StatusOr& other) requires std::is_copy_constructible_v : + m_status{other.m_status} + { + if (m_status.ok()) + { + new (&m_value) T(other.m_value); + } + } + + StatusOr(StatusOr&& other) requires std::is_move_constructible_v : + m_status{std::move(other.m_status)} + { + if (m_status.ok()) + { + new (&m_value) T(std::move(other.m_value)); + } + } + + ~StatusOr() + { + Clear(); + } + + StatusOr& operator=(const StatusOr& other) requires std::is_copy_assignable_v + { + if (this != &other) + { + if (m_status.ok() && other.m_status.ok()) + { + m_value = other.m_value; + } + else if (!m_status.ok() && other.m_status.ok()) + { + new (&m_value) T(other.m_value); + } + else if (m_status.ok() && !other.m_status.ok()) + { + Clear(); + } + m_status = other.m_status; + } + return *this; + } + + StatusOr& operator=(StatusOr&& other) requires std::is_move_assignable_v + { + if (this != &other) + { + if (m_status.ok() && other.m_status.ok()) + { + m_value = std::move(other.m_value); + } + else if (!m_status.ok() && other.m_status.ok()) + { + new (&m_value) T(std::move(other.m_value)); + } + else if (m_status.ok() && !other.m_status.ok()) + { + Clear(); + } + m_status = other.m_status; + } + return *this; + } + + constexpr bool ok() const { return m_status.ok(); } + + friend void DeimosFormat(IWriter* writer, const StatusOr& status) + { + DeimosFormat(writer, status.m_status); + } +}; + } // namespace deimos diff --git a/deimos/core/std.h b/deimos/core/std.h index 0e0336e..47f161a 100644 --- a/deimos/core/std.h +++ b/deimos/core/std.h @@ -25,6 +25,11 @@ template concept unsigned_integral = integral && __is_unsigned(T) template constexpr bool is_trivially_destructible_v = __is_trivially_destructible(T); template constexpr bool is_constructible_v = __is_constructible(T, Args...); +template constexpr bool is_default_constructible_v = __is_constructible(T); +template constexpr bool is_copy_constructible_v = __is_constructible(T, const T&); +template constexpr bool is_move_constructible_v = __is_constructible(T, T&&); +template constexpr bool is_copy_assignable_v = __is_assignable(T, const T&); +template constexpr bool is_move_assignable_v = __is_assignable(T, T&&); template constexpr bool is_trivially_copyable_v = __is_trivially_copyable(T); template constexpr bool _is_same_helper = false; -- cgit