libbase: Add `expected<T, E>::operator bool`

This is a standard API helpful for this construct:

    if (const auto expected = getExpected())

Bug: 185536303
Test: libbase_test
Change-Id: If73b9e4b6de18d0c2763b560443c8ef3a94b3519
diff --git a/expected_test.cpp b/expected_test.cpp
index 47e396a..d35cdee 100644
--- a/expected_test.cpp
+++ b/expected_test.cpp
@@ -812,7 +812,7 @@
 }
 
 TEST(Expected, testConstexpr) {
-  // Compliation error will occur if these expressions can't be
+  // Compilation error will occur if these expressions can't be
   // evaluated at compile time
   constexpr exp_int e(3);
   constexpr exp_int::unexpected_type err(3);
@@ -828,11 +828,13 @@
   static_assert(exp_int(i).value() == 4);
   // copy construct from unexpected
   static_assert(exp_int(err).error() == 3);
-  // move costruct from unexpected
+  // move construct from unexpected
   static_assert(exp_int(unexpected(3)).error() == 3);
   // observers
   static_assert(*exp_int(3) == 3);
   static_assert(exp_int(3).has_value() == true);
+  static_assert(static_cast<bool>(exp_int(3)));
+  static_assert(!static_cast<bool>(exp_int(err)));
   static_assert(exp_int(3).value_or(4) == 3);
 
   typedef expected<const char*, int> exp_s;
diff --git a/include/android-base/expected.h b/include/android-base/expected.h
index 3b9d45f..f9c03cf 100644
--- a/include/android-base/expected.h
+++ b/include/android-base/expected.h
@@ -253,7 +253,7 @@
   ~expected() = default;
 
   // assignment
-  // Note: SFNAIE doesn't work here because assignment operator should be
+  // Note: SFINAE doesn't work here because assignment operator should be
   // non-template. We could workaround this by defining a templated parent class
   // having the assignment operator. This incomplete implementation however
   // doesn't allow us to copy assign expected<T,E> even when T is non-copy
@@ -261,7 +261,7 @@
   // anyway though the error message won't be clear.
   expected& operator=(const expected& rhs) = default;
 
-  // Note for SFNAIE above applies to here as well
+  // Note for SFINAE above applies to here as well
   expected& operator=(expected&& rhs) noexcept(
       std::is_nothrow_move_assignable_v<T>&& std::is_nothrow_move_assignable_v<E>) = default;
 
@@ -332,6 +332,7 @@
 
   constexpr bool has_value() const noexcept { return var_.index() == 0; }
   constexpr bool ok() const noexcept { return has_value(); }
+  constexpr explicit operator bool() const noexcept { return has_value(); }
 
   constexpr const T& value() const& { return std::get<T>(var_); }
   constexpr T& value() & { return std::get<T>(var_); }
@@ -517,7 +518,7 @@
   ~expected() = default;
 
   // assignment
-  // Note: SFNAIE doesn't work here because assignment operator should be
+  // Note: SFINAE doesn't work here because assignment operator should be
   // non-template. We could workaround this by defining a templated parent class
   // having the assignment operator. This incomplete implementation however
   // doesn't allow us to copy assign expected<T,E> even when T is non-copy
@@ -525,7 +526,7 @@
   // anyway though the error message won't be clear.
   expected& operator=(const expected& rhs) = default;
 
-  // Note for SFNAIE above applies to here as well
+  // Note for SFINAE above applies to here as well
   expected& operator=(expected&& rhs) noexcept(std::is_nothrow_move_assignable_v<E>) = default;
 
   template<class G = E>
@@ -559,6 +560,7 @@
   // observers
   constexpr bool has_value() const noexcept { return var_.index() == 0; }
   constexpr bool ok() const noexcept { return has_value(); }
+  constexpr explicit operator bool() const noexcept { return has_value(); }
 
   constexpr void value() const& { if (!has_value()) std::get<0>(var_); }