#pragma once #define _LUNA_SYSTEM_ERROR_EXTENSIONS #include #include #include #include #include #include struct Error { Error(int err) { error = err; } int error; }; template class Result { public: Result(const T& value) : m_value(value), m_has_value(true) { } Result(T&& value) : m_value(move(value)), m_has_value(true) { } Result(const Result& other) : m_value(other.m_value), m_has_value(other.m_has_value), m_error(other.m_error) { } Result(Result&& other) : m_value(move(other.m_value)), m_has_value(other.m_has_value), m_error(other.m_error) { other.m_has_value = false; } Result(const Error& err) : m_value(), m_has_value(false), m_error(err.error) { } bool has_error() const { return !m_has_value; } bool has_value() const { return m_has_value; } int error() const { expect(has_error(), "Result::error() called on a Result that holds a value"); return m_error; } Error release_error() const { expect(has_error(), "Result::release_error() called on a Result that holds a value"); return { m_error }; } const char* error_string() const { expect(has_error(), "Result::error_string() called on a Result that holds a value"); return ::error_string(m_error); } T value() const { expect(has_value(), "Result::value() called on a Result that holds an error"); return m_value.value(); } T expect_value(const char* reason) const { expect(has_value(), reason); return m_value.value(); } T value_or(const T& other) const { return m_value.value_or(other); } bool try_set_value(T& ref) const { return m_value.try_set_value(ref); } Result try_set_value_with_specific_error(T& ref, int error) { if (has_error() && m_error != error) return release_error(); return m_value.try_set_value(ref); } T release_value() { expect(has_value(), "Result::release_value() called on a Result that holds an error"); return m_value.release_value(); } T expect_release_value(const char* reason) { expect(has_value(), reason); return m_value.release_value(); } private: Option m_value; bool m_has_value; int m_error; }; template <> class Result { public: Result() : m_has_error(false) { } Result(const Result& other) : m_has_error(other.m_has_error), m_error(other.m_error) { } Result(Result&& other) : m_has_error(other.m_has_error), m_error(other.m_error) { } Result(const Error& err) : m_has_error(true), m_error(err.error) { } bool has_error() const { return m_has_error; } bool has_value() const { return !m_has_error; } int error() const { expect(has_error(), "Result::error() called on a Result that holds a value"); return m_error; } Error release_error() const { expect(has_error(), "Result::release_error() called on a Result that holds a value"); return { m_error }; } const char* error_string() const { expect(has_error(), "Result::error_string() called on a Result that holds a value"); return ::error_string(m_error); } void value() const { expect(has_value(), "Result::value() called on a Result that holds an error"); return; } void expect_value(const char* reason) const { expect(has_value(), reason); return; } void release_value() const { expect(has_value(), "Result::release_value() called on a Result that holds an error"); return; } void expect_release_value(const char* reason) const { expect(has_value(), reason); return; } private: bool m_has_error; int m_error; }; // clang-format off #define err(x) Error{x} // clang-format on #define TRY(expr) \ ({ \ auto _expr_rc = (expr); \ if (!_expr_rc.has_value()) return _expr_rc.release_error(); \ _expr_rc.release_value(); \ })