diff --git a/source/mijin/container/optional.hpp b/source/mijin/container/optional.hpp index 4e9148d..fb48971 100644 --- a/source/mijin/container/optional.hpp +++ b/source/mijin/container/optional.hpp @@ -8,6 +8,7 @@ #include #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& get() const noexcept; [[nodiscard]] constexpr bool empty() const noexcept { return storage_.empty(); } inline void reset() noexcept; + + + template + auto then(TCallable&& onSuccess, TErrorCallable&& onError = 0) + { + using result_t = std::invoke_result_t>; + + if constexpr (std::is_same_v) + { + if (!empty()) + { + std::invoke(std::forward(onSuccess), get()); + } + else if constexpr (!std::is_same_v) + { + std::invoke(std::forward(onError)); + } + } + else if constexpr (requires(result_t obj) { {obj == NULL_OPTIONAL} -> std::convertible_to; }) + { + if (!empty()) + { + return std::invoke(std::forward(onSuccess), get()); + } + else + { + if constexpr (!std::is_same_v) + { + std::invoke(std::forward(onError)); + } + return NULL_OPTIONAL; + } + } + else + { + static_assert(always_false_v, "Callable must produce void or optional type."); + } + } }; //