#pragma once #include #include #include #include #include "util/numtypes.h" // Define an error type class Error { public: explicit Error(std::string message) : m_Message(std::move(message)) {} [[nodiscard]] fn message() const -> const std::string& { return m_Message; } private: std::string m_Message; }; // Primary template for Result with a default type of void template class Result; // Specialization for Result template <> class Result { public: // Constructors for success and error Result() : m_Result(std::monostate {}) {} Result(const Error& error) : m_Result(error) {} Result(Error&& error) : m_Result(std::move(error)) {} // Check if the result is an error [[nodiscard]] fn isOk() const -> bool { return std::holds_alternative(m_Result); } [[nodiscard]] fn isErr() const -> bool { return std::holds_alternative(m_Result); } // Throw an exception if it is an error void value() const { if (isErr()) { throw std::logic_error("Attempted to access value of an error Result"); } } // Get the error or throw an exception if it is a value [[nodiscard]] fn error() const -> const Error& { if (isOk()) { throw std::logic_error("Attempted to access error of an ok Result"); } return std::get(m_Result); } private: std::variant m_Result; }; // Primary template for Result template class Result { public: // Constructors for success and error Result(const T& value) : m_Result(value) {} Result(T&& value) : m_Result(std::move(value)) {} Result(const Error& error) : m_Result(error) {} Result(Error&& error) : m_Result(std::move(error)) {} // Check if the result is an error [[nodiscard]] fn isOk() const -> bool { return std::holds_alternative(m_Result); } [[nodiscard]] fn isErr() const -> bool { return std::holds_alternative(m_Result); } // Get the value or throw an exception if it is an error fn value() const -> const T& { if (isErr()) { throw std::logic_error("Attempted to access value of an error Result"); } return std::get(m_Result); } // Get the error or throw an exception if it is a value [[nodiscard]] fn error() const -> const Error& { if (isOk()) { throw std::logic_error("Attempted to access error of an ok Result"); } return std::get(m_Result); } // Optional: Get the value or provide a default fn valueOr(const T& defaultValue) const -> T { return isOk() ? std::get(m_Result) : defaultValue; } private: std::variant m_Result; }; template fn Ok(T&& value) { return Result>(std::forward(value)); } inline fn Ok() -> Result { return {}; }