Minor fixes on android::base::expected

This is a follow-up change of 7d89fb164becb44d014023bc03688cef00e179ad.

- Some of the missing conditions for SFNAIE were added
- Fixed indentation
- The assignment operator became "= default"

Bug: 132145659
Test: libbase_test

Change-Id: Ib5232a6e5e1d3df67e185d6e8c03374105c1ce94
diff --git a/base/include/android-base/expected.h b/base/include/android-base/expected.h
index d70e50a..2307217 100644
--- a/base/include/android-base/expected.h
+++ b/base/include/android-base/expected.h
@@ -79,6 +79,15 @@
 #define _NODISCARD_
 #endif
 
+namespace {
+template< class T >
+struct remove_cvref {
+  typedef std::remove_cv_t<std::remove_reference_t<T>> type;
+};
+template< class T >
+using remove_cvref_t = typename remove_cvref<T>::type;
+} // namespace
+
 // Class expected
 template<class T, class E>
 class _NODISCARD_ expected {
@@ -93,7 +102,7 @@
   // constructors
   constexpr expected() = default;
   constexpr expected(const expected& rhs) = default;
-  constexpr expected(expected&& rhs) noexcept  = default;
+  constexpr expected(expected&& rhs) noexcept = default;
 
   template<class U, class G _ENABLE_IF(
     std::is_constructible_v<T, const U&> &&
@@ -173,6 +182,9 @@
 
   template<class U = T _ENABLE_IF(
     std::is_constructible_v<T, U&&> &&
+    !std::is_same_v<remove_cvref_t<U>, std::in_place_t> &&
+    !std::is_same_v<expected<T, E>, remove_cvref_t<U>> &&
+    !std::is_same_v<unexpected<E>, remove_cvref_t<U>> &&
     std::is_convertible_v<U&&,T> /* non-explicit */
   )>
   constexpr expected(U&& v)
@@ -180,6 +192,9 @@
 
   template<class U = T _ENABLE_IF(
     std::is_constructible_v<T, U&&> &&
+    !std::is_same_v<remove_cvref_t<U>, std::in_place_t> &&
+    !std::is_same_v<expected<T, E>, remove_cvref_t<U>> &&
+    !std::is_same_v<unexpected<E>, remove_cvref_t<U>> &&
     !std::is_convertible_v<U&&,T> /* explicit */
   )>
   constexpr explicit expected(U&& v)
@@ -241,38 +256,21 @@
   ~expected() = default;
 
   // assignment
-// TODO(b/132145659) enable assignment operator only when the condition
-// satisfies. SFNAIE 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
-// assignable. The copy assignment will fail by the underlying std::variant
-// anyway though the error message won't be clear.
-//  std::enable_if_t<(
-//    std::is_copy_assignable_v<T> &&
-//    std::is_copy_constructible_v<T> &&
-//    std::is_copy_assignable_v<E> &&
-//    std::is_copy_constructible_v<E> &&
-//    (std::is_nothrow_move_constructible_v<E> ||
-//     std::is_nothrow_move_constructible_v<T>)
-//  ), expected&>
-  expected& operator=(const expected& rhs) {
-    var_ = rhs.var_;
-    return *this;
-  }
-//  std::enable_if_t<(
-//    std::is_move_constructible_v<T> &&
-//    std::is_move_assignable_v<T> &&
-//    std::is_nothrow_move_constructible_v<E> &&
-//    std::is_nothrow_move_assignable_v<E>
-//  ), expected&>
-  expected& operator=(expected&& rhs) noexcept {
-    var_ = std::move(rhs.var_);
-    return *this;
-  }
+  // Note: SFNAIE 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
+  // assignable. The copy assignment will fail by the underlying std::variant
+  // anyway though the error message won't be clear.
+  expected& operator=(const expected& rhs) = default;
+
+  // Note for SFNAIE above applies to here as well
+  expected& operator=(expected&& rhs) = default;
 
   template<class U = T _ENABLE_IF(
     !std::is_void_v<T> &&
+    !std::is_same_v<expected<T,E>, remove_cvref_t<U>> &&
+    !std::conjunction_v<std::is_scalar<T>, std::is_same<T, std::decay_t<U>>> &&
     std::is_constructible_v<T,U> &&
     std::is_assignable_v<T&,U> &&
     std::is_nothrow_move_constructible_v<E>
@@ -283,7 +281,6 @@
   }
 
   template<class G = E>
-  // TODO: std::is_nothrow_copy_constructible_v<E> && std::is_copy_assignable_v<E>
   expected& operator=(const unexpected<G>& rhs) {
     var_ = rhs;
     return *this;
@@ -399,7 +396,7 @@
   friend void swap(expected<T1, E1>&, expected<T1, E1>&) noexcept;
 
  private:
-    std::variant<value_type, unexpected_type> var_;
+  std::variant<value_type, unexpected_type> var_;
 };
 
 template<class T1, class E1, class T2, class E2>
@@ -468,7 +465,9 @@
   constexpr unexpected(unexpected&&) = default;
 
   template<class Err = E _ENABLE_IF(
-    std::is_constructible_v<E, Err>
+    std::is_constructible_v<E, Err> &&
+    !std::is_same_v<remove_cvref_t<E>, std::in_place_t> &&
+    !std::is_same_v<remove_cvref_t<E>, unexpected>
   )>
   constexpr unexpected(Err&& e)
   : val_(std::forward<Err>(e)) {}
@@ -559,7 +558,9 @@
   constexpr const E&& value() const&& noexcept { return std::move(val_); }
   constexpr E&& value() && noexcept { return std::move(val_); }
 
-  void swap(unexpected& other) noexcept { std::swap(val_, other.val_); }
+  void swap(unexpected& other) noexcept(std::is_nothrow_swappable_v<E>) {
+    std::swap(val_, other.val_);
+  }
 
   template<class E1, class E2>
   friend constexpr bool
@@ -570,8 +571,9 @@
 
   template<class E1>
   friend void swap(unexpected<E1>& x, unexpected<E1>& y) noexcept(noexcept(x.swap(y)));
+
  private:
-    E val_;
+  E val_;
 };
 
 template<class E1, class E2>