small result fixes

This commit is contained in:
sascha 2026-07-28 09:52:49 +02:00
parent 06f6166f05
commit 730ab05213
2 changed files with 22 additions and 16 deletions

View File

@ -49,7 +49,7 @@ public:
constexpr ErrorType&& release() { return std::move(error_); } constexpr ErrorType&& release() { return std::move(error_); }
const ErrorType& value() const { return error_; } const ErrorType& value() const { return error_; }
ErrorType value() { return error_; } ErrorType& value() { return error_; }
private: private:
ErrorType error_; ErrorType error_;
@ -80,7 +80,7 @@ public:
const ValueType& value() const { return std::get<value_type>(result_); } const ValueType& value() const { return std::get<value_type>(result_); }
ValueType& value() { return std::get<value_type>(result_); } ValueType& value() { return std::get<value_type>(result_); }
const ErrorType& err() const { return std::get<error_type>(result_); } const ErrorType& err() const { return std::get<error_type>(result_); }
ErrorType err() { return std::get<error_type>(result_); } ErrorType& err() { return std::get<error_type>(result_); }
constexpr const ValueType* operator->() const { return &value(); } constexpr const ValueType* operator->() const { return &value(); }
constexpr ValueType* operator->() { return &std::get<value_type>(result_); } constexpr ValueType* operator->() { return &std::get<value_type>(result_); }
@ -92,7 +92,7 @@ public:
typename SecondValueType = std::invoke_result_t<Func, ValueType >> typename SecondValueType = std::invoke_result_t<Func, ValueType >>
result<SecondValueType, ErrorType> map(Func &&f) { result<SecondValueType, ErrorType> map(Func &&f) {
if (is_ok()) { if (is_ok()) {
return result<SecondValueType, ErrorType>(ok(f(release()))); return result<SecondValueType, ErrorType>(ok(std::invoke(std::forward<Func>(f), release())));
} }
return result<SecondValueType, ErrorType>(failure(release_error())); return result<SecondValueType, ErrorType>(failure(release_error()));
@ -101,31 +101,35 @@ public:
template<typename Func, template<typename Func,
typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType >::value_type> typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType >::value_type>
result<SecondErrorType, ErrorType> map_error(Func &&f) { result<SecondErrorType, ErrorType> map_error(Func &&f) {
if (!is_ok()) { if (!is_error()) {
return result<SecondErrorType, ErrorType>(ok(release())); return failure<SecondErrorType>{std::invoke(std::forward<Func>(f), release_error())};
} }
return result<SecondErrorType, ErrorType>(error(release_error())); return ok<ValueType>(release());
} }
template<typename Func, template<typename Func,
typename SecondValueType = typename std::invoke_result_t<Func, ValueType>::value_type> typename SecondValueType = typename std::invoke_result_t<Func, ValueType>::value_type>
result<SecondValueType, ErrorType> and_then(Func &&f) { result<SecondValueType, ErrorType> and_then(Func &&f) {
using ReturnResult = std::invoke_result_t<Func, ValueType>;
if (is_ok()) { if (is_ok()) {
return f(release()); return std::invoke(std::forward<Func>(f), release());
} }
return result<SecondValueType, ErrorType>(failure(release_error())); return ReturnResult(failure(release_error()));
} }
template<typename Func, template<typename Func,
typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType&& >::value_type> typename FailureType = std::invoke_result_t<Func, ErrorType&&>,
typename SecondErrorType = typename FailureType::value_type>
result<ValueType, SecondErrorType> or_else(Func &&f) { result<ValueType, SecondErrorType> or_else(Func &&f) {
if (is_error()) { if (is_error()) {
return f(release_error()); return result<ValueType, SecondErrorType>(
std::invoke(std::forward<Func>(f), release_error())
);
} }
return result<ValueType, SecondErrorType>(ok(release())); return result<ValueType, SecondErrorType>(ok<ValueType>(release()));
} }
private: private:

View File

@ -5,13 +5,15 @@
#include "matador/utils/result.hpp" #include "matador/utils/result.hpp"
namespace matador::test { namespace matador::test {
namespace {
enum class math_error : int32_t { enum class math_error : int32_t {
OK = 0, OK = 0,
DIVISION_BY_ZERO = 1, DIVISION_BY_ZERO = 1,
FAILURE = 2 FAILURE = 2
}; };
}
utils::result<float, math_error>divide(const float x, const float y) { static utils::result<float, math_error>divide(const float x, const float y) {
if (y == 0) { if (y == 0) {
return utils::failure(math_error::DIVISION_BY_ZERO); return utils::failure(math_error::DIVISION_BY_ZERO);
} }
@ -19,15 +21,15 @@ utils::result<float, math_error>divide(const float x, const float y) {
return utils::ok(x / y); return utils::ok(x / y);
} }
utils::result<float, math_error>multiply(const float x, const float y) { static utils::result<float, math_error>multiply(const float x, const float y) {
return utils::ok(x * y); return utils::ok(x * y);
} }
utils::result<float, math_error>plus(const float x, const float y) { static utils::result<float, math_error>plus(const float x, const float y) {
return utils::ok(x + y); return utils::ok(x + y);
} }
utils::result<void, math_error>action_on_greater_42(const float i) { static utils::result<void, math_error>action_on_greater_42(const float i) {
if (i > 42) { if (i > 42) {
return utils::ok<void>(); return utils::ok<void>();
} }
@ -88,7 +90,7 @@ TEST_CASE("Test result", "[result]") {
REQUIRE(!res2.is_ok()); REQUIRE(!res2.is_ok());
REQUIRE(res2.is_error()); REQUIRE(res2.is_error());
const auto e = res2.err(); const auto e = res2.err();
// REQUIRE(res2.err() == "division by zero error"); REQUIRE(res2.err() == "division by zero error");
res = test::divide(4, 2) res = test::divide(4, 2)
.and_then([](const auto &val) { return test::multiply(val, 5); }) .and_then([](const auto &val) { return test::multiply(val, 5); })