Added Optionl::then() for monad functionality.
This commit is contained in:
parent
f35ee5f038
commit
b66893dda7
@ -8,6 +8,7 @@
|
||||
#include <utility>
|
||||
#include "../debug/assert.hpp"
|
||||
#include "../util/concepts.hpp"
|
||||
#include "../util/traits.hpp"
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
@ -154,6 +155,44 @@ public:
|
||||
[[nodiscard]] inline const std::remove_reference_t<TValue>& get() const noexcept;
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return storage_.empty(); }
|
||||
inline void reset() noexcept;
|
||||
|
||||
|
||||
template<typename TCallable, typename TErrorCallable = int>
|
||||
auto then(TCallable&& onSuccess, TErrorCallable&& onError = 0)
|
||||
{
|
||||
using result_t = std::invoke_result_t<TCallable, std::add_rvalue_reference_t<TValue>>;
|
||||
|
||||
if constexpr (std::is_same_v<result_t, void>)
|
||||
{
|
||||
if (!empty())
|
||||
{
|
||||
std::invoke(std::forward<TCallable>(onSuccess), get());
|
||||
}
|
||||
else if constexpr (!std::is_same_v<TErrorCallable, int>)
|
||||
{
|
||||
std::invoke(std::forward<TErrorCallable>(onError));
|
||||
}
|
||||
}
|
||||
else if constexpr (requires(result_t obj) { {obj == NULL_OPTIONAL} -> std::convertible_to<bool>; })
|
||||
{
|
||||
if (!empty())
|
||||
{
|
||||
return std::invoke(std::forward<TCallable>(onSuccess), get());
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (!std::is_same_v<TErrorCallable, int>)
|
||||
{
|
||||
std::invoke(std::forward<TErrorCallable>(onError));
|
||||
}
|
||||
return NULL_OPTIONAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(always_false_v<TCallable>, "Callable must produce void or optional type.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user