Merge "Add android::base::expected" am: 691e0e154a
am: cfd923af77

Change-Id: I182dd0a98a0c0978367eb058d399715508a705d3
diff --git a/base/Android.bp b/base/Android.bp
index 340f814..58d3a50 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -131,6 +131,7 @@
         "cmsg_test.cpp",
         "endian_test.cpp",
         "errors_test.cpp",
+        "expected_test.cpp",
         "file_test.cpp",
         "logging_test.cpp",
         "macros_test.cpp",
diff --git a/base/expected_test.cpp b/base/expected_test.cpp
new file mode 100644
index 0000000..490ced4
--- /dev/null
+++ b/base/expected_test.cpp
@@ -0,0 +1,745 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android-base/expected.h"
+
+#include <cstdio>
+#include <memory>
+#include <string>
+
+#include <gtest/gtest.h>
+
+using android::base::expected;
+using android::base::unexpected;
+
+typedef expected<int, int> exp_int;
+typedef expected<double, double> exp_double;
+typedef expected<std::string, std::string> exp_string;
+typedef expected<std::pair<std::string, int>, int> exp_pair;
+
+struct T {
+  int a;
+  int b;
+  T() = default;
+  T(int a, int b) noexcept : a(a), b(b) {}
+};
+bool operator==(const T& x, const T& y) {
+  return x.a == y.a && x.b == y.b;
+}
+bool operator!=(const T& x, const T& y) {
+  return x.a != y.a || x.b != y.b;
+}
+
+struct E {
+    std::string message;
+    int cause;
+    E(const std::string& message, int cause) : message(message), cause(cause) {}
+};
+
+typedef expected<T,E> exp_complex;
+
+TEST(Expected, testDefaultConstructible) {
+  exp_int e;
+  EXPECT_TRUE(e.has_value());
+  EXPECT_EQ(0, e.value());
+
+  exp_complex e2;
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(T(0,0), e2.value());
+}
+
+TEST(Expected, testCopyConstructible) {
+  exp_int e;
+  exp_int e2 = e;
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(0, e.value());
+  EXPECT_EQ(0, e2.value());
+}
+
+TEST(Expected, testMoveConstructible) {
+  exp_int e;
+  exp_int e2 = std::move(e);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(0, e.value());
+  EXPECT_EQ(0, e2.value());
+
+  exp_string e3(std::string("hello"));
+  exp_string e4 = std::move(e3);
+
+  EXPECT_TRUE(e3.has_value());
+  EXPECT_TRUE(e4.has_value());
+  EXPECT_EQ("", e3.value()); // e3 is moved
+  EXPECT_EQ("hello", e4.value());
+}
+
+TEST(Expected, testCopyConstructibleFromConvertibleType) {
+  exp_double e = 3.3f;
+  exp_int e2 = e;
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(3.3f, e.value());
+  EXPECT_EQ(3, e2.value());
+}
+
+TEST(Expected, testMoveConstructibleFromConvertibleType) {
+  exp_double e = 3.3f;
+  exp_int e2 = std::move(e);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(3.3f, e.value());
+  EXPECT_EQ(3, e2.value());
+}
+
+TEST(Expected, testConstructibleFromValue) {
+  exp_int e = 3;
+  exp_double e2 = 5.5f;
+  exp_string e3 = std::string("hello");
+  exp_complex e4 = T(10, 20);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_TRUE(e3.has_value());
+  EXPECT_TRUE(e4.has_value());
+  EXPECT_EQ(3, e.value());
+  EXPECT_EQ(5.5f, e2.value());
+  EXPECT_EQ("hello", e3.value());
+  EXPECT_EQ(T(10,20), e4.value());
+}
+
+TEST(Expected, testConstructibleFromMovedValue) {
+  std::string hello = "hello";
+  exp_string e = std::move(hello);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_EQ("hello", e.value());
+  EXPECT_EQ("", hello);
+}
+
+TEST(Expected, testConstructibleFromConvertibleValue) {
+  exp_int e = 3.3f; // double to int
+  exp_string e2 = "hello"; // char* to std::string
+  EXPECT_TRUE(e.has_value());
+  EXPECT_EQ(3, e.value());
+
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ("hello", e2.value());
+}
+
+TEST(Expected, testConstructibleFromUnexpected) {
+  exp_int::unexpected_type unexp = unexpected(10);
+  exp_int e = unexp;
+
+  exp_double::unexpected_type unexp2 = unexpected(10.5f);
+  exp_double e2 = unexp2;
+
+  exp_string::unexpected_type unexp3 = unexpected(std::string("error"));
+  exp_string e3 = unexp3;
+
+  EXPECT_FALSE(e.has_value());
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_FALSE(e3.has_value());
+  EXPECT_EQ(10, e.error());
+  EXPECT_EQ(10.5f, e2.error());
+  EXPECT_EQ("error", e3.error());
+}
+
+TEST(Expected, testMoveConstructibleFromUnexpected) {
+  exp_int e = unexpected(10);
+  exp_double e2 = unexpected(10.5f);
+  exp_string e3 = unexpected(std::string("error"));
+
+  EXPECT_FALSE(e.has_value());
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_FALSE(e3.has_value());
+  EXPECT_EQ(10, e.error());
+  EXPECT_EQ(10.5f, e2.error());
+  EXPECT_EQ("error", e3.error());
+}
+
+TEST(Expected, testConstructibleByForwarding) {
+  exp_string e(std::in_place, 5, 'a');
+  EXPECT_TRUE(e.has_value());
+  EXPECT_EQ("aaaaa", e.value());
+
+  exp_string e2({'a', 'b', 'c'});
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ("abc", e2.value());
+
+  exp_pair e3({"hello", 30});
+  EXPECT_TRUE(e3.has_value());
+  EXPECT_EQ("hello",e3->first);
+  EXPECT_EQ(30,e3->second);
+}
+
+TEST(Expected, testDestructible) {
+  bool destroyed = false;
+  struct T {
+    bool* flag_;
+    T(bool* flag) : flag_(flag) {}
+    ~T() { *flag_ = true; }
+  };
+  {
+    expected<T, int> exp = T(&destroyed);
+  }
+  EXPECT_TRUE(destroyed);
+}
+
+TEST(Expected, testAssignable) {
+  exp_int e = 10;
+  exp_int e2 = 20;
+  e = e2;
+
+  EXPECT_EQ(20, e.value());
+  EXPECT_EQ(20, e2.value());
+
+  exp_int e3 = 10;
+  exp_int e4 = 20;
+  e3 = std::move(e4);
+
+  EXPECT_EQ(20, e3.value());
+  EXPECT_EQ(20, e4.value());
+}
+
+TEST(Expected, testAssignableFromValue) {
+  exp_int e = 10;
+  e = 20;
+  EXPECT_EQ(20, e.value());
+
+  exp_double e2 = 3.5f;
+  e2 = 10.5f;
+  EXPECT_EQ(10.5f, e2.value());
+
+  exp_string e3 = "hello";
+  e3 = "world";
+  EXPECT_EQ("world", e3.value());
+}
+
+TEST(Expected, testAssignableFromUnexpected) {
+  exp_int e = 10;
+  e = unexpected(30);
+  EXPECT_FALSE(e.has_value());
+  EXPECT_EQ(30, e.error());
+
+  exp_double e2 = 3.5f;
+  e2 = unexpected(10.5f);
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_EQ(10.5f, e2.error());
+
+  exp_string e3 = "hello";
+  e3 = unexpected("world");
+  EXPECT_FALSE(e3.has_value());
+  EXPECT_EQ("world", e3.error());
+}
+
+TEST(Expected, testAssignableFromMovedValue) {
+  std::string world = "world";
+  exp_string e = "hello";
+  e = std::move(world);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_EQ("world", e.value());
+  EXPECT_EQ("", world);
+}
+
+TEST(Expected, testAssignableFromMovedUnexpected) {
+  std::string world = "world";
+  exp_string e = "hello";
+  e = unexpected(std::move(world));
+
+  EXPECT_FALSE(e.has_value());
+  EXPECT_EQ("world", e.error());
+  EXPECT_EQ("", world);
+}
+
+TEST(Expected, testEmplace) {
+  struct T {
+    int a;
+    double b;
+    T() {}
+    T(int a, double b) noexcept : a(a), b(b) {}
+  };
+  expected<T, int> exp;
+  T& t = exp.emplace(3, 10.5f);
+
+  EXPECT_TRUE(exp.has_value());
+  EXPECT_EQ(3, t.a);
+  EXPECT_EQ(10.5f, t.b);
+  EXPECT_EQ(3, exp.value().a);
+  EXPECT_EQ(10.5, exp.value().b);
+}
+
+TEST(Expected, testSwapExpectedExpected) {
+  exp_int e = 10;
+  exp_int e2 = 20;
+  e.swap(e2);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(20, e.value());
+  EXPECT_EQ(10, e2.value());
+}
+
+TEST(Expected, testSwapUnexpectedUnexpected) {
+  exp_int e = unexpected(10);
+  exp_int e2 = unexpected(20);
+  e.swap(e2);
+  EXPECT_FALSE(e.has_value());
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_EQ(20, e.error());
+  EXPECT_EQ(10, e2.error());
+}
+
+TEST(Expected, testSwapExpectedUnepected) {
+  exp_int e = 10;
+  exp_int e2 = unexpected(30);
+  e.swap(e2);
+  EXPECT_FALSE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(30, e.error());
+  EXPECT_EQ(10, e2.value());
+}
+
+TEST(Expected, testDereference) {
+  struct T {
+    int a;
+    double b;
+    T() {}
+    T(int a, double b) : a(a), b(b) {}
+  };
+  expected<T, int> exp = T(3, 10.5f);
+
+  EXPECT_EQ(3, exp->a);
+  EXPECT_EQ(10.5f, exp->b);
+
+  EXPECT_EQ(3, (*exp).a);
+  EXPECT_EQ(10.5f, (*exp).b);
+}
+
+TEST(Expected, testTest) {
+  exp_int e = 10;
+  EXPECT_TRUE(e);
+  EXPECT_TRUE(e.has_value());
+
+  exp_int e2 = unexpected(10);
+  EXPECT_FALSE(e2);
+  EXPECT_FALSE(e2.has_value());
+}
+
+TEST(Expected, testGetValue) {
+  exp_int e = 10;
+  EXPECT_EQ(10, e.value());
+  EXPECT_EQ(10, e.value_or(20));
+
+  exp_int e2 = unexpected(10);
+  EXPECT_EQ(10, e2.error());
+  EXPECT_EQ(20, e2.value_or(20));
+}
+
+TEST(Expected, testSameValues) {
+  exp_int e = 10;
+  exp_int e2 = 10;
+  EXPECT_TRUE(e == e2);
+  EXPECT_TRUE(e2 == e);
+  EXPECT_FALSE(e != e2);
+  EXPECT_FALSE(e2 != e);
+}
+
+TEST(Expected, testDifferentValues) {
+  exp_int e = 10;
+  exp_int e2 = 20;
+  EXPECT_FALSE(e == e2);
+  EXPECT_FALSE(e2 == e);
+  EXPECT_TRUE(e != e2);
+  EXPECT_TRUE(e2 != e);
+}
+
+TEST(Expected, testValueWithError) {
+  exp_int e = 10;
+  exp_int e2 = unexpected(10);
+  EXPECT_FALSE(e == e2);
+  EXPECT_FALSE(e2 == e);
+  EXPECT_TRUE(e != e2);
+  EXPECT_TRUE(e2 != e);
+}
+
+TEST(Expected, testSameErrors) {
+  exp_int e = unexpected(10);
+  exp_int e2 = unexpected(10);
+  EXPECT_TRUE(e == e2);
+  EXPECT_TRUE(e2 == e);
+  EXPECT_FALSE(e != e2);
+  EXPECT_FALSE(e2 != e);
+}
+
+TEST(Expected, testDifferentErrors) {
+  exp_int e = unexpected(10);
+  exp_int e2 = unexpected(20);
+  EXPECT_FALSE(e == e2);
+  EXPECT_FALSE(e2 == e);
+  EXPECT_TRUE(e != e2);
+  EXPECT_TRUE(e2 != e);
+}
+
+TEST(Expected, testCompareWithSameValue) {
+  exp_int e = 10;
+  int value = 10;
+  EXPECT_TRUE(e == value);
+  EXPECT_TRUE(value == e);
+  EXPECT_FALSE(e != value);
+  EXPECT_FALSE(value != e);
+}
+
+TEST(Expected, testCompareWithDifferentValue) {
+  exp_int e = 10;
+  int value = 20;
+  EXPECT_FALSE(e == value);
+  EXPECT_FALSE(value == e);
+  EXPECT_TRUE(e != value);
+  EXPECT_TRUE(value != e);
+}
+
+TEST(Expected, testCompareWithSameError) {
+  exp_int e = unexpected(10);
+  exp_int::unexpected_type error = 10;
+  EXPECT_TRUE(e == error);
+  EXPECT_TRUE(error == e);
+  EXPECT_FALSE(e != error);
+  EXPECT_FALSE(error != e);
+}
+
+TEST(Expected, testCompareWithDifferentError) {
+  exp_int e = unexpected(10);
+  exp_int::unexpected_type error = 20;
+  EXPECT_FALSE(e == error);
+  EXPECT_FALSE(error == e);
+  EXPECT_TRUE(e != error);
+  EXPECT_TRUE(error != e);
+}
+
+TEST(Expected, testDivideExample) {
+  struct QR {
+    int quotient;
+    int remainder;
+    QR(int q, int r) noexcept : quotient(q), remainder(r) {}
+    bool operator==(const QR& rhs) const {
+      return quotient == rhs.quotient && remainder == rhs.remainder;
+    }
+    bool operator!=(const QR& rhs) const {
+      return quotient != rhs.quotient || remainder == rhs.remainder;
+    }
+  };
+
+  auto divide = [](int x, int y) -> expected<QR,E> {
+    if (y == 0) {
+      return unexpected(E("divide by zero", -1));
+    } else {
+      return QR(x / y, x % y);
+    }
+  };
+
+  EXPECT_FALSE(divide(10, 0));
+  EXPECT_EQ("divide by zero", divide(10, 0).error().message);
+  EXPECT_EQ(-1, divide(10, 0).error().cause);
+
+  EXPECT_TRUE(divide(10, 3));
+  EXPECT_EQ(QR(3, 1), divide(10, 3));
+}
+
+TEST(Expected, testPair) {
+  auto test = [](bool yes) -> exp_pair {
+    if (yes) {
+      return exp_pair({"yes", 42});
+    } else {
+      return unexpected(42);
+    }
+  };
+
+  auto r = test(true);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("yes", r->first);
+}
+
+// copied from result_test.cpp
+struct ConstructorTracker {
+  static size_t constructor_called;
+  static size_t copy_constructor_called;
+  static size_t move_constructor_called;
+  static size_t copy_assignment_called;
+  static size_t move_assignment_called;
+
+  template <typename T,
+    typename std::enable_if_t<std::is_convertible_v<T, std::string>>* = nullptr>
+  ConstructorTracker(T&& string) : string(string) {
+    ++constructor_called;
+  }
+  ConstructorTracker(const ConstructorTracker& ct) {
+    ++copy_constructor_called;
+    string = ct.string;
+  }
+  ConstructorTracker(ConstructorTracker&& ct) noexcept {
+    ++move_constructor_called;
+    string = std::move(ct.string);
+  }
+  ConstructorTracker& operator=(const ConstructorTracker& ct) {
+    ++copy_assignment_called;
+    string = ct.string;
+    return *this;
+  }
+  ConstructorTracker& operator=(ConstructorTracker&& ct) noexcept {
+    ++move_assignment_called;
+    string = std::move(ct.string);
+    return *this;
+  }
+  static void Reset() {
+    constructor_called = 0;
+    copy_constructor_called = 0;
+    move_constructor_called = 0;
+    copy_assignment_called = 0;
+    move_assignment_called = 0;
+  }
+  std::string string;
+};
+
+size_t ConstructorTracker::constructor_called = 0;
+size_t ConstructorTracker::copy_constructor_called = 0;
+size_t ConstructorTracker::move_constructor_called = 0;
+size_t ConstructorTracker::copy_assignment_called = 0;
+size_t ConstructorTracker::move_assignment_called = 0;
+
+typedef expected<ConstructorTracker, int> exp_track;
+
+TEST(Expected, testNumberOfCopies) {
+  // default constructor
+  ConstructorTracker::Reset();
+  exp_track e("hello");
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // copy constructor
+  ConstructorTracker::Reset();
+  exp_track e2 = e;
+  EXPECT_EQ(0U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // move constructor
+  ConstructorTracker::Reset();
+  exp_track e3 = std::move(e);
+  EXPECT_EQ(0U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // construct from lvalue
+  ConstructorTracker::Reset();
+  ConstructorTracker ct = "hello";
+  exp_track e4(ct);
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // construct from rvalue
+  ConstructorTracker::Reset();
+  ConstructorTracker ct2 = "hello";
+  exp_track e5(std::move(ct2));
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // copy assignment
+  ConstructorTracker::Reset();
+  exp_track e6 = "hello";
+  exp_track e7 = "world";
+  e7 = e6;
+  EXPECT_EQ(2U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // move assignment
+  ConstructorTracker::Reset();
+  exp_track e8 = "hello";
+  exp_track e9 = "world";
+  e9 = std::move(e8);
+  EXPECT_EQ(2U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_assignment_called);
+
+  // swap
+  ConstructorTracker::Reset();
+  exp_track e10 = "hello";
+  exp_track e11 = "world";
+  std::swap(e10, e11);
+  EXPECT_EQ(2U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(2U, ConstructorTracker::move_assignment_called);
+}
+
+TEST(Expected, testNoCopyOnReturn) {
+  auto test = [](const std::string& in) -> exp_track {
+    if (in.empty()) {
+      return "literal string";
+    }
+    if (in == "test2") {
+      return ConstructorTracker(in + in + "2");
+    }
+    ConstructorTracker result(in + " " + in);
+    return result;
+  };
+
+  ConstructorTracker::Reset();
+  auto result1 = test("");
+  ASSERT_TRUE(result1);
+  EXPECT_EQ("literal string", result1->string);
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  ConstructorTracker::Reset();
+  auto result2 = test("test2");
+  ASSERT_TRUE(result2);
+  EXPECT_EQ("test2test22", result2->string);
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  ConstructorTracker::Reset();
+  auto result3 = test("test3");
+  ASSERT_TRUE(result3);
+  EXPECT_EQ("test3 test3", result3->string);
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+}
+
+TEST(Expected, testNested) {
+  expected<exp_string, std::string> e = "hello";
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e.value().has_value());
+  EXPECT_TRUE(e);
+  EXPECT_TRUE(*e);
+  EXPECT_EQ("hello", e.value().value());
+
+  expected<exp_string, std::string> e2 = unexpected("world");
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_FALSE(e2);
+  EXPECT_EQ("world", e2.error());
+
+  expected<exp_string, std::string> e3 = exp_string(unexpected("world"));
+  EXPECT_TRUE(e3.has_value());
+  EXPECT_FALSE(e3.value().has_value());
+  EXPECT_TRUE(e3);
+  EXPECT_FALSE(*e3);
+  EXPECT_EQ("world", e3.value().error());
+}
+
+constexpr bool equals(const char* a, const char* b) {
+  return (a == nullptr && b == nullptr) ||
+      (a != nullptr && b != nullptr && *a == *b &&
+       (*a == '\0' || equals(a + 1, b + 1)));
+}
+
+TEST(Expected, testConstexpr) {
+  // Compliation 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);
+  constexpr int i = 4;
+
+  // default constructor
+  static_assert(exp_int().value() == 0);
+  // copy constructor
+  static_assert(exp_int(e).value() == 3);
+  // move constructor
+  static_assert(exp_int(exp_int(4)).value() == 4);
+  // copy construct from value
+  static_assert(exp_int(i).value() == 4);
+  // copy construct from unexpected
+  static_assert(exp_int(err).error() == 3);
+  // move costruct 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(exp_int(3).value_or(4) == 3);
+
+  typedef expected<const char*, int> exp_s;
+  constexpr exp_s s("hello");
+  constexpr const char* c = "hello";
+  static_assert(equals(exp_s().value(), nullptr));
+  static_assert(equals(exp_s(s).value(), "hello"));
+  static_assert(equals(exp_s(exp_s("hello")).value(), "hello"));
+  static_assert(equals(exp_s("hello").value(), "hello"));
+  static_assert(equals(exp_s(c).value(), "hello"));
+}
+
+TEST(Expected, testWithNonConstructible) {
+   struct AssertNotConstructed {
+     AssertNotConstructed() = delete;
+   };
+
+   expected<int, AssertNotConstructed> v(42);
+   EXPECT_TRUE(v.has_value());
+   EXPECT_EQ(42, v.value());
+
+   expected<AssertNotConstructed, int> e(unexpected(42));
+   EXPECT_FALSE(e.has_value());
+   EXPECT_EQ(42, e.error());
+}
+
+TEST(Expected, testWithMoveOnlyType) {
+  typedef expected<std::unique_ptr<int>,std::unique_ptr<int>> exp_ptr;
+  exp_ptr e(std::make_unique<int>(3));
+  exp_ptr e2(unexpected(std::make_unique<int>(4)));
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_EQ(3, *(e.value()));
+  EXPECT_EQ(4, *(e2.error()));
+
+  e2 = std::move(e);
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(3, *(e2.value()));
+}
diff --git a/base/include/android-base/expected.h b/base/include/android-base/expected.h
new file mode 100644
index 0000000..d70e50a
--- /dev/null
+++ b/base/include/android-base/expected.h
@@ -0,0 +1,600 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <initializer_list>
+#include <type_traits>
+#include <utility>
+#include <variant>
+
+// android::base::expected is an Android implementation of the std::expected
+// proposal.
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0323r7.html
+//
+// Usage:
+// using android::base::expected;
+// using android::base::unexpected;
+//
+// expected<double,std::string> safe_divide(double i, double j) {
+//   if (j == 0) return unexpected("divide by zero");
+//   else return i / j;
+// }
+//
+// void test() {
+//   auto q = safe_divide(10, 0);
+//   if (q) { printf("%f\n", q.value()); }
+//   else { printf("%s\n", q.error().c_str()); }
+// }
+//
+// When the proposal becomes part of the standard and is implemented by
+// libcxx, this will be removed and android::base::expected will be
+// type alias to std::expected.
+//
+
+namespace android {
+namespace base {
+
+// Synopsis
+template<class T, class E>
+    class expected;
+
+template<class E>
+    class unexpected;
+template<class E>
+  unexpected(E) -> unexpected<E>;
+
+template<class E>
+   class bad_expected_access;
+
+template<>
+   class bad_expected_access<void>;
+
+struct unexpect_t {
+   explicit unexpect_t() = default;
+};
+inline constexpr unexpect_t unexpect{};
+
+// macros for SFINAE
+#define _ENABLE_IF(...) \
+  , std::enable_if_t<(__VA_ARGS__)>* = nullptr
+
+// Define NODISCARD_EXPECTED to prevent expected<T,E> from being
+// ignored when used as a return value. This is off by default.
+#ifdef NODISCARD_EXPECTED
+#define _NODISCARD_ [[nodiscard]]
+#else
+#define _NODISCARD_
+#endif
+
+// Class expected
+template<class T, class E>
+class _NODISCARD_ expected {
+ public:
+  using value_type = T;
+  using error_type = E;
+  using unexpected_type = unexpected<E>;
+
+  template<class U>
+  using rebind = expected<U, error_type>;
+
+  // constructors
+  constexpr expected() = default;
+  constexpr expected(const expected& rhs) = default;
+  constexpr expected(expected&& rhs) noexcept  = default;
+
+  template<class U, class G _ENABLE_IF(
+    std::is_constructible_v<T, const U&> &&
+    std::is_constructible_v<E, const G&> &&
+    !std::is_constructible_v<T, expected<U, G>&> &&
+    !std::is_constructible_v<T, expected<U, G>&&> &&
+    !std::is_constructible_v<T, const expected<U, G>&> &&
+    !std::is_constructible_v<T, const expected<U, G>&&> &&
+    !std::is_convertible_v<expected<U, G>&, T> &&
+    !std::is_convertible_v<expected<U, G>&&, T> &&
+    !std::is_convertible_v<const expected<U, G>&, T> &&
+    !std::is_convertible_v<const expected<U, G>&&, T> &&
+    !(!std::is_convertible_v<const U&, T> ||
+     !std::is_convertible_v<const G&, E>) /* non-explicit */
+  )>
+  constexpr expected(const expected<U, G>& rhs) {
+    if (rhs.has_value()) var_ = rhs.value();
+    else var_ = unexpected(rhs.error());
+  }
+
+  template<class U, class G _ENABLE_IF(
+    std::is_constructible_v<T, const U&> &&
+    std::is_constructible_v<E, const G&> &&
+    !std::is_constructible_v<T, expected<U, G>&> &&
+    !std::is_constructible_v<T, expected<U, G>&&> &&
+    !std::is_constructible_v<T, const expected<U, G>&> &&
+    !std::is_constructible_v<T, const expected<U, G>&&> &&
+    !std::is_convertible_v<expected<U, G>&, T> &&
+    !std::is_convertible_v<expected<U, G>&&, T> &&
+    !std::is_convertible_v<const expected<U, G>&, T> &&
+    !std::is_convertible_v<const expected<U, G>&&, T> &&
+    (!std::is_convertible_v<const U&, T> ||
+     !std::is_convertible_v<const G&, E>) /* explicit */
+  )>
+  constexpr explicit expected(const expected<U, G>& rhs) {
+    if (rhs.has_value()) var_ = rhs.value();
+    else var_ = unexpected(rhs.error());
+  }
+
+  template<class U, class G _ENABLE_IF(
+    std::is_constructible_v<T, const U&> &&
+    std::is_constructible_v<E, const G&> &&
+    !std::is_constructible_v<T, expected<U, G>&> &&
+    !std::is_constructible_v<T, expected<U, G>&&> &&
+    !std::is_constructible_v<T, const expected<U, G>&> &&
+    !std::is_constructible_v<T, const expected<U, G>&&> &&
+    !std::is_convertible_v<expected<U, G>&, T> &&
+    !std::is_convertible_v<expected<U, G>&&, T> &&
+    !std::is_convertible_v<const expected<U, G>&, T> &&
+    !std::is_convertible_v<const expected<U, G>&&, T> &&
+    !(!std::is_convertible_v<const U&, T> ||
+     !std::is_convertible_v<const G&, E>) /* non-explicit */
+  )>
+  constexpr expected(expected<U, G>&& rhs) {
+    if (rhs.has_value()) var_ = std::move(rhs.value());
+    else var_ = unexpected(std::move(rhs.error()));
+  }
+
+  template<class U, class G _ENABLE_IF(
+    std::is_constructible_v<T, const U&> &&
+    std::is_constructible_v<E, const G&> &&
+    !std::is_constructible_v<T, expected<U, G>&> &&
+    !std::is_constructible_v<T, expected<U, G>&&> &&
+    !std::is_constructible_v<T, const expected<U, G>&> &&
+    !std::is_constructible_v<T, const expected<U, G>&&> &&
+    !std::is_convertible_v<expected<U, G>&, T> &&
+    !std::is_convertible_v<expected<U, G>&&, T> &&
+    !std::is_convertible_v<const expected<U, G>&, T> &&
+    !std::is_convertible_v<const expected<U, G>&&, T> &&
+    (!std::is_convertible_v<const U&, T> ||
+     !std::is_convertible_v<const G&, E>) /* explicit */
+  )>
+  constexpr explicit expected(expected<U, G>&& rhs) {
+    if (rhs.has_value()) var_ = std::move(rhs.value());
+    else var_ = unexpected(std::move(rhs.error()));
+  }
+
+  template<class U = T _ENABLE_IF(
+    std::is_constructible_v<T, U&&> &&
+    std::is_convertible_v<U&&,T> /* non-explicit */
+  )>
+  constexpr expected(U&& v)
+  : var_(std::in_place_index<0>, std::forward<U>(v)) {}
+
+  template<class U = T _ENABLE_IF(
+    std::is_constructible_v<T, U&&> &&
+    !std::is_convertible_v<U&&,T> /* explicit */
+  )>
+  constexpr explicit expected(U&& v)
+  : var_(std::in_place_index<0>, T(std::forward<U>(v))) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, const G&> &&
+    std::is_convertible_v<const G&, E> /* non-explicit */
+  )>
+  constexpr expected(const unexpected<G>& e)
+  : var_(std::in_place_index<1>, e.value()) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, const G&> &&
+    !std::is_convertible_v<const G&, E> /* explicit */
+  )>
+  constexpr explicit expected(const unexpected<G>& e)
+  : var_(std::in_place_index<1>, E(e.value())) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, G&&> &&
+    std::is_convertible_v<G&&, E> /* non-explicit */
+  )>
+  constexpr expected(unexpected<G>&& e)
+  : var_(std::in_place_index<1>, std::move(e.value())) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, G&&> &&
+    !std::is_convertible_v<G&&, E> /* explicit */
+  )>
+  constexpr explicit expected(unexpected<G>&& e)
+  : var_(std::in_place_index<1>, E(std::move(e.value()))) {}
+
+  template<class... Args _ENABLE_IF(
+    std::is_constructible_v<T, Args&&...>
+  )>
+  constexpr explicit expected(std::in_place_t, Args&&... args)
+  : var_(std::in_place_index<0>, std::forward<Args>(args)...) {}
+
+  template<class U, class... Args _ENABLE_IF(
+    std::is_constructible_v<T, std::initializer_list<U>&, Args...>
+  )>
+  constexpr explicit expected(std::in_place_t, std::initializer_list<U> il, Args&&... args)
+  : var_(std::in_place_index<0>, il, std::forward<Args>(args)...) {}
+
+  template<class... Args _ENABLE_IF(
+    std::is_constructible_v<E, Args...>
+  )>
+  constexpr explicit expected(unexpect_t, Args&&... args)
+  : var_(unexpected_type(std::forward<Args>(args)...)) {}
+
+  template<class U, class... Args _ENABLE_IF(
+    std::is_constructible_v<E, std::initializer_list<U>&, Args...>
+  )>
+  constexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args&&... args)
+  : var_(unexpected_type(il, std::forward<Args>(args)...)) {}
+
+  // destructor
+  ~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;
+  }
+
+  template<class U = T _ENABLE_IF(
+    !std::is_void_v<T> &&
+    std::is_constructible_v<T,U> &&
+    std::is_assignable_v<T&,U> &&
+    std::is_nothrow_move_constructible_v<E>
+  )>
+  expected& operator=(U&& rhs) {
+    var_ = T(std::forward<U>(rhs));
+    return *this;
+  }
+
+  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;
+  }
+
+  template<class G = E _ENABLE_IF(
+    std::is_nothrow_move_constructible_v<G> &&
+    std::is_move_assignable_v<G>
+  )>
+  expected& operator=(unexpected<G>&& rhs) {
+    var_ = std::move(rhs);
+    return *this;
+  }
+
+  // modifiers
+  template<class... Args _ENABLE_IF(
+    std::is_nothrow_constructible_v<T, Args...>
+  )>
+  T& emplace(Args&&... args) {
+    expected(std::in_place, std::forward<Args>(args)...).swap(*this);
+    return value();
+  }
+
+  template<class U, class... Args _ENABLE_IF(
+    std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>
+  )>
+  T& emplace(std::initializer_list<U> il, Args&&... args) {
+    expected(std::in_place, il, std::forward<Args>(args)...).swap(*this);
+    return value();
+  }
+
+  // swap
+  template<typename U = T, typename = std::enable_if_t<(
+    std::is_swappable_v<U> &&
+    std::is_swappable_v<E> &&
+    (std::is_move_constructible_v<U> ||
+     std::is_move_constructible_v<E>))>>
+  void swap(expected& rhs) noexcept(
+    std::is_nothrow_move_constructible_v<T> &&
+    std::is_nothrow_swappable_v<T> &&
+    std::is_nothrow_move_constructible_v<E> &&
+    std::is_nothrow_swappable_v<E>) {
+    var_.swap(rhs.var_);
+  }
+
+  // observers
+  constexpr const T* operator->() const { return std::addressof(value()); }
+  constexpr T* operator->() { return std::addressof(value()); }
+  constexpr const T& operator*() const& { return value(); }
+  constexpr T& operator*() & { return value(); }
+  constexpr const T&& operator*() const&& { return std::move(std::get<T>(var_)); }
+  constexpr T&& operator*() && { return std::move(std::get<T>(var_)); }
+
+  constexpr explicit operator bool() const noexcept { return has_value(); }
+  constexpr bool has_value() const noexcept { return var_.index() == 0; }
+
+  constexpr const T& value() const& { return std::get<T>(var_); }
+  constexpr T& value() & { return std::get<T>(var_); }
+  constexpr const T&& value() const&& { return std::move(std::get<T>(var_)); }
+  constexpr T&& value() && { return std::move(std::get<T>(var_)); }
+
+  constexpr const E& error() const& { return std::get<unexpected_type>(var_).value(); }
+  constexpr E& error() & { return std::get<unexpected_type>(var_).value(); }
+  constexpr const E&& error() const&& { return std::move(std::get<unexpected_type>(var_)).value(); }
+  constexpr E&& error() && { return std::move(std::get<unexpected_type>(var_)).value(); }
+
+  template<class U _ENABLE_IF(
+    std::is_copy_constructible_v<T> &&
+    std::is_convertible_v<U, T>
+  )>
+  constexpr T value_or(U&& v) const& {
+    if (has_value()) return value();
+    else return static_cast<T>(std::forward<U>(v));
+  }
+
+  template<class U _ENABLE_IF(
+    std::is_move_constructible_v<T> &&
+    std::is_convertible_v<U, T>
+  )>
+  constexpr T value_or(U&& v) && {
+    if (has_value()) return std::move(value());
+    else return static_cast<T>(std::forward<U>(v));
+  }
+
+  // expected equality operators
+  template<class T1, class E1, class T2, class E2>
+  friend constexpr bool operator==(const expected<T1, E1>& x, const expected<T2, E2>& y);
+  template<class T1, class E1, class T2, class E2>
+  friend constexpr bool operator!=(const expected<T1, E1>& x, const expected<T2, E2>& y);
+
+  // comparison with T
+  template<class T1, class E1, class T2>
+  friend constexpr bool operator==(const expected<T1, E1>&, const T2&);
+  template<class T1, class E1, class T2>
+  friend constexpr bool operator==(const T2&, const expected<T1, E1>&);
+  template<class T1, class E1, class T2>
+  friend constexpr bool operator!=(const expected<T1, E1>&, const T2&);
+  template<class T1, class E1, class T2>
+  friend constexpr bool operator!=(const T2&, const expected<T1, E1>&);
+
+  // Comparison with unexpected<E>
+  template<class T1, class E1, class E2>
+  friend constexpr bool operator==(const expected<T1, E1>&, const unexpected<E2>&);
+  template<class T1, class E1, class E2>
+  friend constexpr bool operator==(const unexpected<E2>&, const expected<T1, E1>&);
+  template<class T1, class E1, class E2>
+  friend constexpr bool operator!=(const expected<T1, E1>&, const unexpected<E2>&);
+  template<class T1, class E1, class E2>
+  friend constexpr bool operator!=(const unexpected<E2>&, const expected<T1, E1>&);
+
+  // Specialized algorithms
+  template<class T1, class E1>
+  friend void swap(expected<T1, E1>&, expected<T1, E1>&) noexcept;
+
+ private:
+    std::variant<value_type, unexpected_type> var_;
+};
+
+template<class T1, class E1, class T2, class E2>
+constexpr bool operator==(const expected<T1, E1>& x, const expected<T2, E2>& y) {
+  if (x.has_value() != y.has_value()) {
+    return false;
+  } else if (!x.has_value()) {
+    return x.error() == y.error();
+  } else {
+    return *x == *y;
+  }
+}
+
+template<class T1, class E1, class T2, class E2>
+constexpr bool operator!=(const expected<T1, E1>& x, const expected<T2, E2>& y) {
+  if (x.has_value() != y.has_value()) {
+    return true;
+  } else if (!x.has_value()) {
+    return x.error() != y.error();
+  } else {
+    return *x != *y;
+  }
+}
+
+// comparison with T
+template<class T1, class E1, class T2>
+constexpr bool operator==(const expected<T1, E1>& x, const T2& y) {
+  return x.has_value() && (*x == y);
+}
+template<class T1, class E1, class T2>
+constexpr bool operator==(const T2& x, const expected<T1, E1>& y) {
+  return y.has_value() && (x == *y);
+}
+template<class T1, class E1, class T2>
+constexpr bool operator!=(const expected<T1, E1>& x, const T2& y) {
+  return !x.has_value() || (*x != y);
+}
+template<class T1, class E1, class T2>
+constexpr bool operator!=(const T2& x, const expected<T1, E1>& y) {
+  return !y.has_value() || (x != *y);
+}
+
+// Comparison with unexpected<E>
+template<class T1, class E1, class E2>
+constexpr bool operator==(const expected<T1, E1>& x, const unexpected<E2>& y) {
+  return !x.has_value() && (x.error() == y.value());
+}
+template<class T1, class E1, class E2>
+constexpr bool operator==(const unexpected<E2>& x, const expected<T1, E1>& y) {
+  return !y.has_value() && (x.value() == y.error());
+}
+template<class T1, class E1, class E2>
+constexpr bool operator!=(const expected<T1, E1>& x, const unexpected<E2>& y) {
+  return x.has_value() || (x.error() != y.value());
+}
+template<class T1, class E1, class E2>
+constexpr bool operator!=(const unexpected<E2>& x, const expected<T1, E1>& y) {
+  return y.has_value() || (x.value() != y.error());
+}
+
+template<class E>
+class unexpected {
+ public:
+  // constructors
+  constexpr unexpected(const unexpected&) = default;
+  constexpr unexpected(unexpected&&) = default;
+
+  template<class Err = E _ENABLE_IF(
+    std::is_constructible_v<E, Err>
+  )>
+  constexpr unexpected(Err&& e)
+  : val_(std::forward<Err>(e)) {}
+
+  template<class U, class... Args _ENABLE_IF(
+    std::is_constructible_v<E, std::initializer_list<U>&, Args...>
+  )>
+  constexpr explicit unexpected(std::in_place_t, std::initializer_list<U> il, Args&&... args)
+  : val_(il, std::forward<Args>(args)...) {}
+
+  template<class Err _ENABLE_IF(
+    std::is_constructible_v<E, Err> &&
+    !std::is_constructible_v<E, unexpected<Err>&> &&
+    !std::is_constructible_v<E, unexpected<Err>> &&
+    !std::is_constructible_v<E, const unexpected<Err>&> &&
+    !std::is_constructible_v<E, const unexpected<Err>> &&
+    !std::is_convertible_v<unexpected<Err>&, E> &&
+    !std::is_convertible_v<unexpected<Err>, E> &&
+    !std::is_convertible_v<const unexpected<Err>&, E> &&
+    !std::is_convertible_v<const unexpected<Err>, E> &&
+    std::is_convertible_v<Err, E> /* non-explicit */
+  )>
+  constexpr unexpected(const unexpected<Err>& rhs)
+  : val_(rhs.value()) {}
+
+  template<class Err _ENABLE_IF(
+    std::is_constructible_v<E, Err> &&
+    !std::is_constructible_v<E, unexpected<Err>&> &&
+    !std::is_constructible_v<E, unexpected<Err>> &&
+    !std::is_constructible_v<E, const unexpected<Err>&> &&
+    !std::is_constructible_v<E, const unexpected<Err>> &&
+    !std::is_convertible_v<unexpected<Err>&, E> &&
+    !std::is_convertible_v<unexpected<Err>, E> &&
+    !std::is_convertible_v<const unexpected<Err>&, E> &&
+    !std::is_convertible_v<const unexpected<Err>, E> &&
+    !std::is_convertible_v<Err, E> /* explicit */
+  )>
+  constexpr explicit unexpected(const unexpected<Err>& rhs)
+  : val_(E(rhs.value())) {}
+
+  template<class Err _ENABLE_IF(
+    std::is_constructible_v<E, Err> &&
+    !std::is_constructible_v<E, unexpected<Err>&> &&
+    !std::is_constructible_v<E, unexpected<Err>> &&
+    !std::is_constructible_v<E, const unexpected<Err>&> &&
+    !std::is_constructible_v<E, const unexpected<Err>> &&
+    !std::is_convertible_v<unexpected<Err>&, E> &&
+    !std::is_convertible_v<unexpected<Err>, E> &&
+    !std::is_convertible_v<const unexpected<Err>&, E> &&
+    !std::is_convertible_v<const unexpected<Err>, E> &&
+    std::is_convertible_v<Err, E> /* non-explicit */
+  )>
+  constexpr unexpected(unexpected<Err>&& rhs)
+  : val_(std::move(rhs.value())) {}
+
+  template<class Err _ENABLE_IF(
+    std::is_constructible_v<E, Err> &&
+    !std::is_constructible_v<E, unexpected<Err>&> &&
+    !std::is_constructible_v<E, unexpected<Err>> &&
+    !std::is_constructible_v<E, const unexpected<Err>&> &&
+    !std::is_constructible_v<E, const unexpected<Err>> &&
+    !std::is_convertible_v<unexpected<Err>&, E> &&
+    !std::is_convertible_v<unexpected<Err>, E> &&
+    !std::is_convertible_v<const unexpected<Err>&, E> &&
+    !std::is_convertible_v<const unexpected<Err>, E> &&
+    !std::is_convertible_v<Err, E> /* explicit */
+  )>
+  constexpr explicit unexpected(unexpected<Err>&& rhs)
+  : val_(E(std::move(rhs.value()))) {}
+
+  // assignment
+  constexpr unexpected& operator=(const unexpected&) = default;
+  constexpr unexpected& operator=(unexpected&&) = default;
+  template<class Err = E>
+  constexpr unexpected& operator=(const unexpected<Err>& rhs) {
+    val_ = rhs.value();
+    return *this;
+  }
+  template<class Err = E>
+  constexpr unexpected& operator=(unexpected<Err>&& rhs) {
+    val_ = std::forward<E>(rhs.value());
+    return *this;
+  }
+
+  // observer
+  constexpr const E& value() const& noexcept { return val_; }
+  constexpr E& value() & noexcept { return val_; }
+  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_); }
+
+  template<class E1, class E2>
+  friend constexpr bool
+  operator==(const unexpected<E1>& e1, const unexpected<E2>& e2);
+  template<class E1, class E2>
+  friend constexpr bool
+  operator!=(const unexpected<E1>& e1, const unexpected<E2>& e2);
+
+  template<class E1>
+  friend void swap(unexpected<E1>& x, unexpected<E1>& y) noexcept(noexcept(x.swap(y)));
+ private:
+    E val_;
+};
+
+template<class E1, class E2>
+constexpr bool
+operator==(const unexpected<E1>& e1, const unexpected<E2>& e2) {
+  return e1.value() == e2.value();
+}
+
+template<class E1, class E2>
+constexpr bool
+operator!=(const unexpected<E1>& e1, const unexpected<E2>& e2) {
+  return e1.value() != e2.value();
+}
+
+template<class E1>
+void swap(unexpected<E1>& x, unexpected<E1>& y) noexcept(noexcept(x.swap(y))) {
+  x.swap(y);
+}
+
+// TODO: bad_expected_access class
+
+#undef _ENABLE_IF
+#undef _NODISCARD_
+
+}  // namespace base
+}  // namespace android