diff --git a/src/Utils/Utils/Result.h b/src/Utils/Utils/Result.h new file mode 100644 index 00000000..2e932393 --- /dev/null +++ b/src/Utils/Utils/Result.h @@ -0,0 +1,124 @@ +#pragma once + +#include +#include + +using NoResult = std::monostate; + +// Can be replaced by std::expected with c++23 +template class Result +{ +public: + Result(TResult result) + : m_data(std::variant(std::in_place_index<0>, std::move(result))) + { + } + + static Result Ok(TResult result) + { + return Result(std::in_place_index<0>, std::move(result)); + } + + static Result Bad(TError error) + { + return Result(std::in_place_index<1>, std::move(error)); + } + + constexpr operator bool() const noexcept + { + return m_data.index() == 0; + } + + constexpr bool has_value() const noexcept + { + return m_data.index() == 0; + } + + constexpr std::add_lvalue_reference_t value() & + { + return std::get<0, TResult>(m_data); + } + + constexpr std::add_const_t> value() const& + { + return std::get<0, TResult>(m_data); + } + + constexpr std::add_rvalue_reference_t value() && + { + return std::move(std::get<0, TResult>(m_data)); + } + + constexpr std::add_const_t> value() const&& + { + return std::move(std::get<0, TResult>(m_data)); + } + + constexpr std::add_lvalue_reference_t operator*() & + { + return std::get<0, TResult>(m_data); + } + + constexpr std::add_const_t> operator*() const& + { + return std::get<0, TResult>(m_data); + } + + constexpr std::add_rvalue_reference_t operator*() && + { + return std::move(std::get<0, TResult>(m_data)); + } + + constexpr std::add_const_t> operator*() const&& + { + return std::move(std::get<0, TResult>(m_data)); + } + + constexpr std::add_pointer_t operator->() + { + return std::get<0, TResult>(m_data); + } + + constexpr std::add_const_t> operator->() const + { + return std::get<0, TResult>(m_data); + } + + constexpr std::add_lvalue_reference_t error() & + { + return std::get<1, TError>(m_data); + } + + constexpr std::add_const_t> error() const& + { + return std::get<1, TError>(m_data); + } + + constexpr std::add_rvalue_reference_t error() && + { + return std::move(std::get<1, TError>(m_data)); + } + + constexpr std::add_const_t> error() const&& + { + return std::move(std::get<1, TError>(m_data)); + } + +private: + explicit Result(std::variant data) + : m_data(std::move(data)) + { + } + + std::variant m_data; +}; + +#define ENSURE_RESULT_VAR(var) \ + if (!(var)) \ + return (var); +#define ENSURE_RESULT(expr) \ + { \ + const auto result = (expr); \ + if (!result) \ + return result; \ + }