Added Optionl::then() for monad functionality.

This commit is contained in:
Patrick 2024-07-26 18:51:08 +02:00
parent f35ee5f038
commit b66893dda7

View File

@ -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.");
}
}
};
//