diff options
author | Dominik Laskowski <domlaskowski@google.com> | 2022-09-28 10:38:46 -0400 |
---|---|---|
committer | Dominik Laskowski <domlaskowski@google.com> | 2023-03-07 13:14:02 -0500 |
commit | 07a71cdbe9c2a790e53c3c73dd0156a9c91727d2 (patch) | |
tree | 56b9615b6ae3fd80a4f6d45f41849f2e197fe96c /include | |
parent | 85795340f3b9deb44eb03e4aa498e7e14ae1522e (diff) | |
download | native-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.h | 10 | ||||
-rw-r--r-- | include/ftl/optional.h | 14 |
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> |