FTL: Add Optional<T>::or_else

Bug: 185536303
Test: ftl_test
Change-Id: Idf0bac4711111c8cb28e8624bb146a76ec1ff38b
diff --git a/include/ftl/details/optional.h b/include/ftl/details/optional.h
index bff7c1e..e45c1f5 100644
--- a/include/ftl/details/optional.h
+++ b/include/ftl/details/optional.h
@@ -54,5 +54,15 @@
 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 a818128..94d8e3d 100644
--- a/include/ftl/optional.h
+++ b/include/ftl/optional.h
@@ -96,13 +96,25 @@
     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>