diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-04-24 23:13:42 +0200 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-04-24 23:13:42 +0200 |
commit | 08eece258ceff7824250454906bff013a7303c28 (patch) | |
tree | b0aff3b1bceeb748dc176545b6cfdd5c68f908b7 /deimos/core/status.h | |
parent | 31c220c7178f3a8ae7a803e46d3d568d7ff56848 (diff) |
Some work on StatusOr
Diffstat (limited to 'deimos/core/status.h')
-rw-r--r-- | deimos/core/status.h | 134 |
1 files changed, 132 insertions, 2 deletions
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<typename T>
+class StatusOr
+{
+ deimos_StaticAssert(!std::is_constructible_v<T, Status>);
+
+ struct Dummy{};
+
+ Status m_status;
+
+ union {
+ Dummy m_dummy;
+ T m_value;
+ };
+
+ void Clear()
+ {
+ if constexpr (!std::is_trivially_destructible_v<T>)
+ {
+ if (m_status.ok())
+ {
+ (&m_value)->~T();
+ }
+ }
+ }
+
+public:
+ explicit StatusOr() requires std::is_default_constructible_v<T> :
+ m_value{}
+ {}
+
+ template<typename... Args>
+ StatusOr(Args&&... args) requires std::is_constructible_v<T, Args...> : // NOLINT
+ m_value{std::forward<Args>(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<T> :
+ 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<T> :
+ 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<T>
+ {
+ 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<T>
+ {
+ 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<T>& status)
+ {
+ DeimosFormat(writer, status.m_status);
+ }
+};
+
} // namespace deimos
|