1
1
mirror of https://github.com/trafi/maybe-result-cpp synced 2024-11-26 04:26:06 +01:00

Add map_err and some docs.

This commit is contained in:
Nerijus Arlauskas 2016-07-07 01:30:56 +03:00
parent 52c783731e
commit dc721316df
4 changed files with 76 additions and 1 deletions

@ -195,11 +195,40 @@ namespace maybe {
return std::addressof(err_val); return std::addressof(err_val);
} }
/**
* Maps a result<T, E> to result<U, E> (where U is return value of F(T)) by applying a function F to a
* contained ok value, leaving an err value untouched.
*
* This function can be used to compose the results of two functions.
*
* @param f F(T) -> U
* @return maybe::result<U, E>
*/
template <typename F> template <typename F>
constexpr auto map(F f) noexcept -> maybe::result<typename std::result_of<F(T)>::type, E>; constexpr auto map(F f) noexcept -> maybe::result<typename std::result_of<F(T)>::type, E>;
/**
* Maps a result<T, E> to result<T, U> (where U is return value of F(E)) by applying a function to a
* contained err value, leaving an ok value untouched.
*
* This function can be used to pass through a successful result while changing an error.
*
* @param f F(E) -> U
* @return maybe::result<T, U>
*/
template <typename F> template <typename F>
constexpr auto and_then(F f) noexcept -> typename std::result_of<F(T)>::type; constexpr auto map_err(F f) noexcept -> maybe::result<T, typename std::result_of<F(E)>::type>;
/**
* Calls op if the result is ok, otherwise returns the err value of self.
*
* This function can be used for control flow based on result values.
*
* @param f F(T) -> maybe::result<U, E>
* @return maybe::result<U, E>
*/
template <typename F>
constexpr auto and_then(F op) noexcept -> typename std::result_of<F(T)>::type;
private: private:
constexpr void copy_from(const result<T, E>& other) noexcept; constexpr void copy_from(const result<T, E>& other) noexcept;

@ -109,6 +109,19 @@ constexpr auto maybe::result<T, E>::map(F f) noexcept
return return_result_t::ok(f(std::forward<T>(ok_value()))); return return_result_t::ok(f(std::forward<T>(ok_value())));
}; };
template <typename T, typename E>
template <typename F>
constexpr auto maybe::result<T, E>::map_err(F f) noexcept
-> maybe::result<T, typename std::result_of<F(E)>::type>
{
typedef maybe::result<T, typename std::result_of<F(E)>::type> return_result_t;
if (is_ok()) {
return return_result_t::ok(std::forward<T>(ok_value()));
}
return return_result_t::err(f(std::forward<E>(err_value())));
};
template <typename T, typename E> template <typename T, typename E>
template <typename F> template <typename F>
constexpr auto maybe::result<T, E>::and_then(F f) noexcept -> typename std::result_of<F(T)>::type constexpr auto maybe::result<T, E>::and_then(F f) noexcept -> typename std::result_of<F(T)>::type

@ -6,6 +6,7 @@ add_executable(${TARGET}
main.cpp main.cpp
result_tests.cpp result_tests.cpp
result_map_tests.cpp result_map_tests.cpp
result_map_err_tests.cpp
result_and_then_tests.cpp result_and_then_tests.cpp
) )

@ -0,0 +1,32 @@
#include "catch.hpp"
#include <maybe/result.hpp>
class A final {
public:
A(std::string value) : value(value)
{
}
std::string value;
};
using maybe::result;
TEST_CASE("result_map_err")
{
SECTION("converts err bool to err int")
{
auto a = result<A, bool>::err(true);
auto b = a.map_err([](bool v) { return v ? 42 : 43; });
REQUIRE(!b);
REQUIRE(b.err_value() == 42);
}
SECTION("does not convert anything and returns ok if not err")
{
auto a = result<A, bool>::ok(A("hi"));
auto b = a.map_err([](bool v) { return v ? 42 : 43; });
REQUIRE(b);
REQUIRE(b.ok_value().value == "hi");
}
}