FTL: Add Optional<T>::and_then
Bug: 185536303
Test: ftl_test
Change-Id: Ic907a662a2090ad1363bd329e7d758b2acef55ad
diff --git a/include/ftl/optional.h b/include/ftl/optional.h
index daf4502..a0a95c4 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.
@@ -37,30 +38,59 @@
// 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();
}
};