summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDominik Laskowski <domlaskowski@google.com>2022-09-28 10:38:46 -0400
committerDominik Laskowski <domlaskowski@google.com>2023-03-07 13:14:02 -0500
commit07a71cdbe9c2a790e53c3c73dd0156a9c91727d2 (patch)
tree56b9615b6ae3fd80a4f6d45f41849f2e197fe96c /include
parent85795340f3b9deb44eb03e4aa498e7e14ae1522e (diff)
downloadnative-07a71cdbe9c2a790e53c3c73dd0156a9c91727d2.tar.gz
FTL: Add Optional<T>::or_else
Bug: 185536303 Test: ftl_test Change-Id: Idf0bac4711111c8cb28e8624bb146a76ec1ff38b
Diffstat (limited to 'include')
-rw-r--r--include/ftl/details/optional.h10
-rw-r--r--include/ftl/optional.h14
2 files changed, 23 insertions, 1 deletions
diff --git a/include/ftl/details/optional.h b/include/ftl/details/optional.h
index bff7c1e000..e45c1f5e23 100644
--- a/include/ftl/details/optional.h
+++ b/include/ftl/details/optional.h
@@ -54,5 +54,15 @@ struct and_then_result {
template <typename F, typename T>
using and_then_result_t = typename and_then_result<F, T>::type;
+template <typename F, typename T>
+struct or_else_result {
+ using type = remove_cvref_t<std::invoke_result_t<F>>;
+ static_assert(std::is_same_v<type, std::optional<T>> || std::is_same_v<type, Optional<T>>,
+ "or_else function must return an optional T");
+};
+
+template <typename F, typename T>
+using or_else_result_t = typename or_else_result<F, T>::type;
+
} // namespace details
} // namespace android::ftl
diff --git a/include/ftl/optional.h b/include/ftl/optional.h
index a818128c92..94d8e3d7cb 100644
--- a/include/ftl/optional.h
+++ b/include/ftl/optional.h
@@ -96,13 +96,25 @@ struct Optional final : std::optional<T> {
return R();
}
+ // Returns this Optional<T> if not nullopt, or else the Optional<T> returned by the function F.
+ template <typename F>
+ constexpr auto or_else(F&& f) const& -> details::or_else_result_t<F, T> {
+ if (has_value()) return *this;
+ return std::forward<F>(f)();
+ }
+
+ template <typename F>
+ constexpr auto or_else(F&& f) && -> details::or_else_result_t<F, T> {
+ if (has_value()) return std::move(*this);
+ return std::forward<F>(f)();
+ }
+
// Delete new for this class. Its base doesn't have a virtual destructor, and
// if it got deleted via base class pointer, it would cause undefined
// behavior. There's not a good reason to allocate this object on the heap
// anyway.
static void* operator new(size_t) = delete;
static void* operator new[](size_t) = delete;
-
};
template <typename T, typename U>