#pragma once #include #include #include #include namespace fmt { template static std::string format(const CharT(&)[N], const Args&...); } namespace rsx { namespace exception_utils { enum soft_exception_error_code { none = 0, range_exception = 1, invalid_enum = 2 }; struct soft_exception_t { soft_exception_error_code error = soft_exception_error_code::none; soft_exception_t() = default; soft_exception_t(soft_exception_error_code code) : error(code) {} bool empty() const { return error == soft_exception_error_code::none; } std::string to_string() const { switch (error) { case soft_exception_error_code::none: return "No error"; case soft_exception_error_code::range_exception: return "Bad Range"; case soft_exception_error_code::invalid_enum: return "Invalid enum"; default: return "Unknown Error"; } } }; } template concept ErrorType = requires (E & e) { { e.empty() } -> std::same_as; }; template class expected { T value; E error{}; public: [[ nodiscard ]] expected(const T& value_) : value(value_) {} [[ nodiscard ]] expected(const E& error_) : error(error_) { ensure(!error.empty()); } operator T() const { ensure(error.empty()); return value; } T operator *() const { ensure(error.empty()); return value; } template>> operator bool() const { return error.empty(); } operator std::pair() const { return { value, error }; } bool operator == (const T& other) const { return error.empty() && value == other; } std::string to_string() const { if (error.empty()) { return fmt::format("%s", value); } if constexpr (std::is_same_v) { return error.to_string(); } return fmt::format("%s", error); } }; }