#pragma once #include "../DefaultInclude.hpp" #include #include #include namespace geode { namespace { struct AnyType { explicit AnyType() = delete; }; template concept ConvertibleToResult = std::is_convertible_v< std::remove_reference_t, std::remove_reference_t > || std::is_same_v< std::remove_reference_t, std::remove_reference_t >; using DefaultValue = std::monostate; using DefaultError = std::string; } template class [[nodiscard]] NewResult { public: using value_type = std::remove_reference_t; using error_type = std::remove_reference_t; // for some reason doing requires causes errors with pch... static_assert( std::is_copy_constructible_v || std::is_move_constructible_v, "T must be copiable or movable!" ); static_assert( std::is_copy_constructible_v || std::is_move_constructible_v, "E must be copiable or movable!" ); protected: std::variant m_value; public: bool isOk() const { return std::holds_alternative(m_value); } bool isErr() const { return std::holds_alternative(m_value); } explicit NewResult(value_type const& value) requires std::is_copy_constructible_v : m_value(value) {} explicit NewResult(value_type&& value) requires std::is_move_constructible_v : m_value(std::forward(value)) {} explicit NewResult(error_type const& value) requires std::is_copy_constructible_v : m_value(value) {} explicit NewResult(error_type&& value) requires std::is_move_constructible_v : m_value(std::forward(value)) {} NewResult(NewResult const& other) requires std::is_copy_constructible_v && std::is_copy_constructible_v = default; NewResult(NewResult&& other) requires ( !std::is_copy_constructible_v || !std::is_copy_constructible_v ) = default; template requires ConvertibleToResult && ConvertibleToResult NewResult(NewResult const& other) requires std::is_copy_constructible_v && std::is_copy_constructible_v : m_value(other.isOk() ? other.unwrap() : other.unwrapErr()) {} template requires ConvertibleToResult && ConvertibleToResult NewResult(NewResult&& other) requires ( !std::is_copy_constructible_v || !std::is_copy_constructible_v ) : m_value(other.isOk() ? other.unwrap() : other.unwrapErr()) {} template requires ConvertibleToResult NewResult(NewResult const& other) requires std::is_copy_constructible_v && std::is_copy_constructible_v : NewResult(value_type(other.unwrap())) {} template requires ConvertibleToResult NewResult(NewResult const& other) requires std::is_copy_constructible_v && std::is_copy_constructible_v : m_value(std::forward(other.unwrapErr())) {} template requires ConvertibleToResult NewResult(NewResult&& other) requires ( !std::is_copy_constructible_v || !std::is_copy_constructible_v ) : m_value(other.unwrap()) {} template requires ConvertibleToResult NewResult(NewResult&& other) requires ( !std::is_copy_constructible_v || !std::is_copy_constructible_v ) : NewResult(std::forward(other.unwrapErr())) {} value_type unwrap() const requires std::is_copy_constructible_v { return std::get(m_value); } value_type&& unwrap() requires (!std::is_copy_constructible_v) { return std::move(std::get(m_value)); } error_type unwrapErr() const requires std::is_copy_constructible_v { return std::get(m_value); } error_type&& unwrapErr() requires (!std::is_copy_constructible_v) { return std::move(std::get(m_value)); } explicit operator bool() const requires ( !std::is_same_v && !std::is_same_v ) { return this->isOk(); } }; template class [[nodiscard]] NewResult { public: using value_type = std::remove_reference_t; using error_type = std::remove_reference_t; // for some reason doing requires causes errors with pch... static_assert( std::is_copy_constructible_v || std::is_move_constructible_v, "T must be copiable or movable!" ); protected: bool m_success; value_type m_value; public: bool isOk() const { return m_success; } bool isErr() const { return !m_success; } explicit NewResult(value_type const& value, bool success) requires std::is_copy_constructible_v : m_value(value), m_success(success) {} explicit NewResult(value_type&& value, bool success) requires std::is_move_constructible_v : m_value(std::forward(value)), m_success(success) {} NewResult(NewResult const& other) requires std::is_copy_constructible_v = default; NewResult(NewResult&& other) requires (!std::is_copy_constructible_v) = default; template requires ConvertibleToResult && ConvertibleToResult NewResult(NewResult const& other) requires std::is_copy_constructible_v : m_value(other.isOk() ? other.unwrap() : other.unwrapErr()), m_success(other.isOk()) {} template requires ConvertibleToResult && ConvertibleToResult NewResult(NewResult&& other) requires ( !std::is_copy_constructible_v ) : m_value(other.isOk() ? other.unwrap() : other.unwrapErr()), m_success(other.isOk()) {} template requires ConvertibleToResult NewResult(NewResult const& other) requires std::is_copy_constructible_v : NewResult(value_type(other.unwrap()), true) {} template requires ConvertibleToResult NewResult(NewResult&& other) requires ( !std::is_copy_constructible_v ) : NewResult(std::forward(other.unwrap()), true) {} template requires ConvertibleToResult NewResult(NewResult const& other) requires std::is_copy_constructible_v : NewResult(error_type(other.unwrapErr()), false) {} template requires ConvertibleToResult NewResult(NewResult&& other) requires ( !std::is_copy_constructible_v ) : NewResult(std::forward(other.unwrapErr()), false) {} value_type unwrap() const requires std::is_copy_constructible_v { return m_value; } value_type&& unwrap() requires (!std::is_copy_constructible_v) { return std::move(m_value); } error_type unwrapErr() const requires std::is_copy_constructible_v { return m_value; } error_type&& unwrapErr() requires (!std::is_copy_constructible_v) { return std::move(m_value); } explicit operator bool() const requires ( !std::is_same_v ) { return this->isOk(); } }; template requires std::is_copy_constructible_v NewResult NewOk(T value = T()) { return NewResult(value); } template requires (!std::is_copy_constructible_v) NewResult NewOk(T&& value) { return NewResult(std::forward(value)); } template requires std::is_copy_constructible_v NewResult NewErr(E error = E()) { return NewResult(error); } template requires (!std::is_copy_constructible_v) NewResult NewErr(E&& error) { return NewResult(std::forward(error)); } #define GEODE_UNWRAP_INTO(into, ...) \ auto GEODE_CONCAT(res_, __LINE__) = (__VA_ARGS__);\ if (GEODE_CONCAT(res_, __LINE__).isErr()) {\ return NewErr(std::move(GEODE_CONCAT(res_, __LINE__).unwrapErr()));\ }\ into = std::move(GEODE_CONCAT(res_, __LINE__).unwrap()) #define GEODE_UNWRAP(...) \ { auto GEODE_CONCAT(res_, __LINE__) = (__VA_ARGS__);\ if (GEODE_CONCAT(res_, __LINE__).isErr()) {\ return NewErr(std::move(GEODE_CONCAT(res_, __LINE__).unwrapErr()));\ } } }