diff options
Diffstat (limited to 'include/ftl/optional.h')
-rw-r--r-- | include/ftl/optional.h | 64 |
1 files changed, 50 insertions, 14 deletions
diff --git a/include/ftl/optional.h b/include/ftl/optional.h index daf4502bd2..626507fd8f 100644 --- a/include/ftl/optional.h +++ b/include/ftl/optional.h @@ -18,9 +18,10 @@ #include <functional> #include <optional> -#include <type_traits> #include <utility> +#include <ftl/details/optional.h> + namespace android::ftl { // Superset of std::optional<T> with monadic operations, as proposed in https://wg21.link/P0798R8. @@ -31,41 +32,76 @@ template <typename T> struct Optional final : std::optional<T> { using std::optional<T>::optional; + // Implicit downcast. + Optional(std::optional<T> other) : std::optional<T>(std::move(other)) {} + using std::optional<T>::has_value; using std::optional<T>::value; // Returns Optional<U> where F is a function that maps T to U. template <typename F> constexpr auto transform(F&& f) const& { - using U = std::remove_cv_t<std::invoke_result_t<F, decltype(value())>>; - if (has_value()) return Optional<U>(std::invoke(std::forward<F>(f), value())); - return Optional<U>(); + using R = details::transform_result_t<F, decltype(value())>; + if (has_value()) return R(std::invoke(std::forward<F>(f), value())); + return R(); } template <typename F> constexpr auto transform(F&& f) & { - using U = std::remove_cv_t<std::invoke_result_t<F, decltype(value())>>; - if (has_value()) return Optional<U>(std::invoke(std::forward<F>(f), value())); - return Optional<U>(); + using R = details::transform_result_t<F, decltype(value())>; + if (has_value()) return R(std::invoke(std::forward<F>(f), value())); + return R(); } template <typename F> constexpr auto transform(F&& f) const&& { - using U = std::invoke_result_t<F, decltype(std::move(value()))>; - if (has_value()) return Optional<U>(std::invoke(std::forward<F>(f), std::move(value()))); - return Optional<U>(); + using R = details::transform_result_t<F, decltype(std::move(value()))>; + if (has_value()) return R(std::invoke(std::forward<F>(f), std::move(value()))); + return R(); } template <typename F> constexpr auto transform(F&& f) && { - using U = std::invoke_result_t<F, decltype(std::move(value()))>; - if (has_value()) return Optional<U>(std::invoke(std::forward<F>(f), std::move(value()))); - return Optional<U>(); + using R = details::transform_result_t<F, decltype(std::move(value()))>; + if (has_value()) return R(std::invoke(std::forward<F>(f), std::move(value()))); + return R(); + } + + // Returns Optional<U> where F is a function that maps T to Optional<U>. + template <typename F> + constexpr auto and_then(F&& f) const& { + using R = details::and_then_result_t<F, decltype(value())>; + if (has_value()) return std::invoke(std::forward<F>(f), value()); + return R(); + } + + template <typename F> + constexpr auto and_then(F&& f) & { + using R = details::and_then_result_t<F, decltype(value())>; + if (has_value()) return std::invoke(std::forward<F>(f), value()); + return R(); + } + + template <typename F> + constexpr auto and_then(F&& f) const&& { + using R = details::and_then_result_t<F, decltype(std::move(value()))>; + if (has_value()) return std::invoke(std::forward<F>(f), std::move(value())); + return R(); + } + + template <typename F> + constexpr auto and_then(F&& f) && { + using R = details::and_then_result_t<F, decltype(std::move(value()))>; + if (has_value()) return std::invoke(std::forward<F>(f), std::move(value())); + return R(); } }; -// Deduction guide. +// Deduction guides. template <typename T> Optional(T) -> Optional<T>; +template <typename T> +Optional(std::optional<T>) -> Optional<T>; + } // namespace android::ftl |