summaryrefslogtreecommitdiff
path: root/asl/status_or.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'asl/status_or.hpp')
-rw-r--r--asl/status_or.hpp358
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
+