Support std::optional in CF_EXPECT.

Also replaces some use of `if constexpr` with overload resolution.

Test: m -j
Bug: 218418464
Change-Id: I2b9d600180f50b38a2c61a4241f0d1e0f1f8f5f2
diff --git a/common/libs/utils/result.h b/common/libs/utils/result.h
index ff9087b..2b732e4 100644
--- a/common/libs/utils/result.h
+++ b/common/libs/utils/result.h
@@ -15,6 +15,7 @@
 
 #pragma once
 
+#include <optional>
 #include <type_traits>
 
 #include <android-base/logging.h>
@@ -52,8 +53,13 @@
                               << CF_ERR_MSG() << "\n  with errno " << errno
 
 template <typename T>
-typename std::conditional_t<std::is_void_v<T>, bool, T>
-VoidSafeResultDereference(Result<T>&& result) {
+T OutcomeDereference(std::optional<T>&& value) {
+  return std::move(*value);
+}
+
+template <typename T>
+typename std::conditional_t<std::is_void_v<T>, bool, T> OutcomeDereference(
+    Result<T>&& result) {
   if constexpr (std::is_void<T>::value) {
     return result.ok();
   } else {
@@ -63,41 +69,59 @@
 
 template <typename T>
 typename std::enable_if<std::is_convertible_v<T, bool>, T>::type
-VoidSafeResultDereference(T&& value) {
+OutcomeDereference(T&& value) {
   return std::forward<T>(value);
 }
 
+inline bool TypeIsSuccess(bool value) { return value; }
+
 template <typename T>
-bool IsOkOrTrue(T&& value) {
-  if constexpr (std::is_convertible_v<T, bool>) {
-    return (bool)value;
-  } else {
-    return value.ok();
-  }
+bool TypeIsSuccess(std::optional<T>& value) {
+  return value.has_value();
 }
 
 template <typename T>
-auto ErrorFromBoolOrResult(T&& value) {
-  if constexpr (std::is_convertible_v<T, bool>) {
-    return (android::base::Error() << "Received `false`").str();
-  } else {
-    return value.error();
-  }
+bool TypeIsSuccess(Result<T>& value) {
+  return value.ok();
+}
+
+template <typename T>
+bool TypeIsSuccess(Result<T>&& value) {
+  return value.ok();
+}
+
+inline auto ErrorFromType(bool) {
+  return (android::base::Error() << "Received `false`").str();
+}
+
+template <typename T>
+inline auto ErrorFromType(std::optional<T>) {
+  return (android::base::Error() << "Received empty optional").str();
+}
+
+template <typename T>
+auto ErrorFromType(Result<T>& value) {
+  return value.error();
+}
+
+template <typename T>
+auto ErrorFromType(Result<T>&& value) {
+  return value.error();
 }
 
 #define CF_EXPECT_OVERLOAD(_1, _2, NAME, ...) NAME
 
-#define CF_EXPECT2(RESULT, MSG)                                          \
-  ({                                                                     \
-    decltype(RESULT)&& macro_intermediate_result = RESULT;               \
-    if (!IsOkOrTrue(macro_intermediate_result)) {                        \
-      return android::base::Error()                                      \
-             << ErrorFromBoolOrResult(macro_intermediate_result) << "\n" \
-             << MSG << "\n"                                              \
-             << CF_ERR_MSG() << "\n"                                     \
-             << "  for CF_EXPECT(" << #RESULT << ")";                    \
-    };                                                                   \
-    VoidSafeResultDereference(std::move(macro_intermediate_result));     \
+#define CF_EXPECT2(RESULT, MSG)                                  \
+  ({                                                             \
+    decltype(RESULT)&& macro_intermediate_result = RESULT;       \
+    if (!TypeIsSuccess(macro_intermediate_result)) {             \
+      return android::base::Error()                              \
+             << ErrorFromType(macro_intermediate_result) << "\n" \
+             << MSG << "\n"                                      \
+             << CF_ERR_MSG() << "\n"                             \
+             << "  for CF_EXPECT(" << #RESULT << ")";            \
+    };                                                           \
+    OutcomeDereference(std::move(macro_intermediate_result));    \
   })
 
 #define CF_EXPECT1(RESULT) CF_EXPECT2(RESULT, "Received error")