#pragma once #include #include "error.hpp" template class Result { public: Result(const T& res) : _value(res), _error(ErrorCode::Success) {} Result(T&& res) : _value(std::move(res)), _error(ErrorCode::Success) {} Result(ErrorCode err) : _error(err) {} Result() : _error(ErrorCode::Unknown) {} bool has_error() const { return _error != ErrorCode::Success; } bool has_value() const { return !has_error(); } T& value() { return _value; } T& operator*() { return _value; } T release_value() { return std::move(_value); } ErrorCode error() { return _error; } private: T _value; ErrorCode _error; }; template <> class Result { public: using ResultType = void; Result(Result&& res) = default; Result(ErrorCode err) : err(err) {} Result() : err(ErrorCode::Success) {} Result& operator=(Result&& res) = default; bool has_error() const { return err != ErrorCode::Success; } bool has_value() const { return !has_error(); } void value() {} void release_value() {} ErrorCode error() { return err; } private: ErrorCode err; }; #define TRY(m) \ (({ \ auto ___res = (m); \ if (!___res.has_value()) return ___res.error(); \ std::move(___res); \ }).release_value()) #define DIEX(m) \ (({ \ auto ___res = (m); \ if (!___res.has_value()) { \ const char* err = geterr(); \ if (err == 0) \ fprintf(stderr, "%s:%d assertion failed\n", __FILE__, __LINE__); \ else \ fprintf(stderr, "%s\n", err); \ exit(EXIT_FAILURE); \ } \ std::move(___res); \ }).release_value())