about summary refs log tree commit diff
path: root/absl
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2018-04-20T16·16-0700
committerJon Cohen <cohenjon@google.com>2018-04-20T16·30-0400
commitfaf0a1b90374eab44e8956973b0e13febdcf3377 (patch)
tree63a7fd12a50b15c4a321e8373c1bbd975df0b7ba /absl
parent5b535401665cc6aa96d54a5c9b0901153d97210f (diff)
- 551e205ef49682a1cb7e6e0cda46957fbcf88edd Release absl::variant. by Xiaoyi Zhang <zhangxy@google.com>
  - 01c52f640594d073c6e54c47e7853b25522cf085 Update comments in absl::variant (and minor changes to ab... by Tom Manshreck <shreck@google.com>
  - 064465e1e6b158abd8c38fd1942b4fc464b57d6a Documentation change. by Abseil Team <absl-team@google.com>
  - 58df2c8a27e80c9ea21d87c1acee8019246377c9 Relocates SetCountdown and UnsetCountdown to the exceptio... by Abseil Team <absl-team@google.com>
  - fd9d248d0948d472f2543f7fd9c0ae4a1cd60d01 Clarify thread_annotation.h documentation around local va... by Abseil Team <absl-team@google.com>
  - 0d0abaf7f0945ac5f2c5f49e78afe1b326d5aca0 Typo fix in comments. by Abseil Team <absl-team@google.com>
  - 67286d587cbd07508a81e5b8147c245a5b5538b4 Internal change. by Xiaoyi Zhang <zhangxy@google.com>

GitOrigin-RevId: 551e205ef49682a1cb7e6e0cda46957fbcf88edd
Change-Id: I1a343b080187293cb5f892a309618b5712e7aa14
Diffstat (limited to 'absl')
-rw-r--r--absl/base/config.h24
-rw-r--r--absl/base/exception_safety_testing_test.cc4
-rw-r--r--absl/base/internal/exception_safety_testing.h19
-rw-r--r--absl/base/thread_annotations.h31
-rw-r--r--absl/meta/type_traits.h19
-rw-r--r--absl/strings/str_join.h2
-rw-r--r--absl/time/time.h23
-rw-r--r--absl/types/BUILD.bazel42
-rw-r--r--absl/types/CMakeLists.txt15
-rw-r--r--absl/types/any.h4
-rw-r--r--absl/types/bad_any_cast.h33
-rw-r--r--absl/types/bad_optional_access.h25
-rw-r--r--absl/types/bad_variant_access.cc58
-rw-r--r--absl/types/bad_variant_access.h64
-rw-r--r--absl/types/internal/variant.h1387
-rw-r--r--absl/types/optional.h5
-rw-r--r--absl/types/variant.h838
-rw-r--r--absl/types/variant_test.cc2622
-rw-r--r--absl/utility/utility.h9
19 files changed, 5172 insertions, 52 deletions
diff --git a/absl/base/config.h b/absl/base/config.h
index 500bc8c810b3..3eb24abf2331 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -382,6 +382,19 @@
 #endif
 #endif
 
+// ABSL_HAVE_STD_VARIANT
+//
+// Checks whether C++17 std::optional is available.
+#ifdef ABSL_HAVE_STD_VARIANT
+#error "ABSL_HAVE_STD_VARIANT cannot be directly set."
+#endif
+
+#ifdef __has_include
+#if __has_include(<variant>) && __cplusplus >= 201703L
+#define ABSL_HAVE_STD_VARIANT 1
+#endif
+#endif
+
 // ABSL_HAVE_STD_STRING_VIEW
 //
 // Checks whether C++17 std::string_view is available.
@@ -396,17 +409,18 @@
 #endif
 
 // For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than
-// the support for <optional>, <any>, <string_view>. So we use _MSC_VER to check
-// whether we have VS 2017 RTM (when <optional>, <any>, <string_view> is
-// implemented) or higher.
-// Also, `__cplusplus` is not correctly set by MSVC, so we use `_MSVC_LANG` to
-// check the language version.
+// the support for <optional>, <any>, <string_view>, <variant>. So we use
+// _MSC_VER to check whether we have VS 2017 RTM (when <optional>, <any>,
+// <string_view>, <variant> is implemented) or higher. Also, `__cplusplus` is
+// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language
+// version.
 // TODO(zhangxy): fix tests before enabling aliasing for `std::any`,
 // `std::string_view`.
 #if defined(_MSC_VER) && _MSC_VER >= 1910 && \
     ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402)
 // #define ABSL_HAVE_STD_ANY 1
 #define ABSL_HAVE_STD_OPTIONAL 1
+#define ABSL_HAVE_STD_VARIANT 1
 // #define ABSL_HAVE_STD_STRING_VIEW 1
 #endif
 
diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc
index 041d780fa5be..94a7e4f7480c 100644
--- a/absl/base/exception_safety_testing_test.cc
+++ b/absl/base/exception_safety_testing_test.cc
@@ -27,7 +27,9 @@
 
 namespace absl {
 namespace {
+using ::absl::exceptions_internal::SetCountdown;
 using ::absl::exceptions_internal::TestException;
+using ::absl::exceptions_internal::UnsetCountdown;
 
 // EXPECT_NO_THROW can't inspect the thrown inspection in general.
 template <typename F>
@@ -54,7 +56,7 @@ TEST_F(ThrowingValueTest, Throws) {
   // It's not guaranteed that every operator only throws *once*.  The default
   // ctor only throws once, though, so use it to make sure we only throw when
   // the countdown hits 0
-  exceptions_internal::countdown = 2;
+  SetCountdown(2);
   ExpectNoThrow([]() { ThrowingValue<> bomb; });
   ExpectNoThrow([]() { ThrowingValue<> bomb; });
   EXPECT_THROW(ThrowingValue<> bomb, TestException);
diff --git a/absl/base/internal/exception_safety_testing.h b/absl/base/internal/exception_safety_testing.h
index 3493b5e2325d..48a292b3e1af 100644
--- a/absl/base/internal/exception_safety_testing.h
+++ b/absl/base/internal/exception_safety_testing.h
@@ -94,6 +94,12 @@ class TestBadAllocException : public std::bad_alloc, public TestException {
 
 extern int countdown;
 
+// Allows the countdown variable to be set manually (defaulting to the initial
+// value of 0)
+inline void SetCountdown(int i = 0) { countdown = i; }
+// Sets the countdown to the terminal value -1
+inline void UnsetCountdown() { SetCountdown(-1); }
+
 void MaybeThrow(absl::string_view msg, bool throw_bad_alloc = false);
 
 testing::AssertionResult FailureMessage(const TestException& e,
@@ -134,7 +140,7 @@ absl::optional<testing::AssertionResult> TestSingleInvariantAtCountdownImpl(
     const Invariant& invariant) {
   auto t_ptr = factory();
   absl::optional<testing::AssertionResult> current_res;
-  exceptions_internal::countdown = count;
+  SetCountdown(count);
   try {
     operation(t_ptr.get());
   } catch (const exceptions_internal::TestException& e) {
@@ -143,7 +149,7 @@ absl::optional<testing::AssertionResult> TestSingleInvariantAtCountdownImpl(
       *current_res << e.what() << " failed invariant check";
     }
   }
-  exceptions_internal::countdown = -1;
+  UnsetCountdown();
   return current_res;
 }
 
@@ -196,11 +202,6 @@ inline absl::optional<testing::AssertionResult> TestAllInvariantsAtCountdown(
 extern exceptions_internal::NoThrowTag no_throw_ctor;
 extern exceptions_internal::StrongGuaranteeTagType strong_guarantee;
 
-// These are useful for tests which just construct objects and make sure there
-// are no leaks.
-inline void SetCountdown() { exceptions_internal::countdown = 0; }
-inline void UnsetCountdown() { exceptions_internal::countdown = -1; }
-
 // A test class which is convertible to bool.  The conversion can be
 // instrumented to throw at a controlled time.
 class ThrowingBool {
@@ -731,10 +732,10 @@ struct ConstructorTracker {
 template <typename T, typename... Args>
 T TestThrowingCtor(Args&&... args) {
   struct Cleanup {
-    ~Cleanup() { UnsetCountdown(); }
+    ~Cleanup() { exceptions_internal::UnsetCountdown(); }
   } c;
   for (int count = 0;; ++count) {
-    exceptions_internal::countdown = count;
+    exceptions_internal::SetCountdown(count);
     try {
       return T(std::forward<Args>(args)...);
     } catch (const exceptions_internal::TestException&) {
diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h
index 0da3badc4e2d..8d30b9324b52 100644
--- a/absl/base/thread_annotations.h
+++ b/absl/base/thread_annotations.h
@@ -47,10 +47,17 @@
 // mutex. GUARDED_BY() allows the user to specify a particular mutex that
 // should be held when accessing the annotated variable.
 //
+// Although this annotation (and PT_GUARDED_BY, below) cannot be applied to
+// local variables, a local variable and its associated mutex can often be
+// combined into a small class or struct, thereby allowing the annotation.
+//
 // Example:
 //
-//   Mutex mu;
-//   int p1 GUARDED_BY(mu);
+//   class Foo {
+//     Mutex mu_;
+//     int p1_ GUARDED_BY(mu_);
+//     ...
+//   };
 #define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
 
 // PT_GUARDED_BY()
@@ -59,17 +66,20 @@
 // by a mutex when dereferencing the pointer.
 //
 // Example:
-//   Mutex mu;
-//   int *p1 PT_GUARDED_BY(mu);
+//   class Foo {
+//     Mutex mu_;
+//     int *p1_ PT_GUARDED_BY(mu_);
+//     ...
+//   };
 //
 // Note that a pointer variable to a shared memory location could itself be a
 // shared variable.
 //
 // Example:
 //
-//     // `q`, guarded by `mu1`, points to a shared memory location that is
-//     // guarded by `mu2`:
-//     int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
+//   // `q_`, guarded by `mu1_`, points to a shared memory location that is
+//   // guarded by `mu2_`:
+//   int *q_ GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
 #define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
 
 // ACQUIRED_AFTER() / ACQUIRED_BEFORE()
@@ -80,10 +90,13 @@
 // (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
 // and ACQUIRED_BEFORE.)
 //
+// As with GUARDED_BY, this is only applicable to mutexes that are shared
+// fields or global variables.
+//
 // Example:
 //
-//   Mutex m1;
-//   Mutex m2 ACQUIRED_AFTER(m1);
+//   Mutex m1_;
+//   Mutex m2_ ACQUIRED_AFTER(m1_);
 #define ACQUIRED_AFTER(...) \
   THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
 
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index ac5d8e1ca7f8..bb1b0baf1ab3 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -36,6 +36,7 @@
 #define ABSL_META_TYPE_TRAITS_H_
 
 #include <stddef.h>
+#include <functional>
 #include <type_traits>
 
 #include "absl/base/config.h"
@@ -349,5 +350,23 @@ using underlying_type_t = typename std::underlying_type<T>::type;
 template <typename T>
 using result_of_t = typename std::result_of<T>::type;
 
+namespace type_traits_internal {
+template <typename Key, typename = size_t>
+struct IsHashable : std::false_type {};
+
+template <typename Key>
+struct IsHashable<Key,
+                  decltype(std::declval<std::hash<Key>>()(std::declval<Key>()))>
+    : std::true_type {};
+
+template <typename Key>
+struct IsHashEnabled
+    : absl::conjunction<std::is_default_constructible<std::hash<Key>>,
+                        std::is_copy_constructible<std::hash<Key>>,
+                        std::is_destructible<std::hash<Key>>,
+                        std::is_copy_assignable<std::hash<Key>>,
+                        IsHashable<Key>> {};
+}  // namespace type_traits_internal
+
 }  // namespace absl
 #endif  // ABSL_META_TYPE_TRAITS_H_
diff --git a/absl/strings/str_join.h b/absl/strings/str_join.h
index 47337490d0bf..bd4d0e1d9324 100644
--- a/absl/strings/str_join.h
+++ b/absl/strings/str_join.h
@@ -165,7 +165,7 @@ DereferenceFormatter() {
 //
 // Example 1:
 //   // Joins a collection of strings. This pattern also works with a collection
-//   // of `asbl::string_view` or even `const char*`.
+//   // of `absl::string_view` or even `const char*`.
 //   std::vector<std::string> v = {"foo", "bar", "baz"};
 //   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("foo-bar-baz", s);
diff --git a/absl/time/time.h b/absl/time/time.h
index daf0b1559f58..30c49d4123ed 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -880,7 +880,8 @@ extern const char RFC1123_no_wday[];  // %d %b %E4Y %H:%M:%S %z
 // provided format std::string. Uses strftime()-like formatting options, with
 // the following extensions:
 //
-//   - %Ez  - RFC3339-compatible numeric time zone (+hh:mm or -hh:mm)
+//   - %Ez  - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)
+//   - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)
 //   - %E#S - Seconds with # digits of fractional precision
 //   - %E*S - Seconds with full fractional precision (a literal '*')
 //   - %E#f - Fractional seconds with # digits of precision
@@ -894,8 +895,8 @@ extern const char RFC1123_no_wday[];  // %d %b %E4Y %H:%M:%S %z
 // year.  A year outside of [-999:9999] when formatted with %E4Y will produce
 // more than four characters, just like %Y.
 //
-// We recommend that format strings include %Ez so that the result uniquely
-// identifies a time instant.
+// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z)
+// so that the result uniquely identifies a time instant.
 //
 // Example:
 //
@@ -929,7 +930,8 @@ inline std::ostream& operator<<(std::ostream& os, Time t) {
 // Parses an input std::string according to the provided format std::string and
 // returns the corresponding `absl::Time`. Uses strftime()-like formatting
 // options, with the same extensions as FormatTime(), but with the
-// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f.
+// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f.  %Ez
+// and %E*z also accept the same inputs.
 //
 // %Y consumes as many numeric characters as it can, so the matching data
 // should always be terminated with a non-numeric.  %E4Y always consumes
@@ -940,10 +942,11 @@ inline std::ostream& operator<<(std::ostream& os, Time t) {
 //   "1970-01-01 00:00:00.0 +0000"
 //
 // For example, parsing a std::string of "15:45" (%H:%M) will return an absl::Time
-// that represents "1970-01-01 15:45:00.0 +0000".  Note: Since ParseTime()
-// returns time instants, it makes the most sense to parse fully-specified
-// date/time strings that include a UTC offset (%z/%Ez), such as those
-// matching RFC3339_full above.
+// that represents "1970-01-01 15:45:00.0 +0000".
+//
+// Note that since ParseTime() returns time instants, it makes the most sense
+// to parse fully-specified date/time strings that include a UTC offset (%z,
+// %Ez, or %E*z).
 //
 // Note also that `absl::ParseTime()` only heeds the fields year, month, day,
 // hour, minute, (fractional) second, and UTC offset.  Other fields, like
@@ -974,8 +977,8 @@ bool ParseTime(const std::string& format, const std::string& input, Time* time,
                std::string* err);
 
 // Like ParseTime() above, but if the format std::string does not contain a UTC
-// offset specification (%z/%Ez) then the input is interpreted in the given
-// TimeZone.  This means that the input, by itself, does not identify a
+// offset specification (%z/%Ez/%E*z) then the input is interpreted in the
+// given TimeZone.  This means that the input, by itself, does not identify a
 // unique instant.  Being time-zone dependent, it also admits the possibility
 // of ambiguity or non-existence, in which case the "pre" time (as defined
 // for ConvertDateTime()) is returned.  For these reasons we recommend that
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index c2f033870ab0..0bdb2f78aee0 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -165,6 +165,17 @@ cc_library(
     ],
 )
 
+cc_library(
+    name = "bad_variant_access",
+    srcs = ["bad_variant_access.cc"],
+    hdrs = ["bad_variant_access.h"],
+    copts = ABSL_EXCEPTIONS_FLAG + ABSL_DEFAULT_COPTS,
+    deps = [
+        "//absl/base",
+        "//absl/base:config",
+    ],
+)
+
 cc_test(
     name = "optional_test",
     size = "small",
@@ -181,3 +192,34 @@ cc_test(
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "variant",
+    srcs = ["internal/variant.h"],
+    hdrs = ["variant.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        ":bad_variant_access",
+        "//absl/base:base_internal",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/meta:type_traits",
+        "//absl/utility",
+    ],
+)
+
+cc_test(
+    name = "variant_test",
+    size = "small",
+    srcs = ["variant_test.cc"],
+    copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
+    deps = [
+        ":variant",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/memory",
+        "//absl/meta:type_traits",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index fd71f38b85ee..f51d126f8160 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -20,6 +20,7 @@ list(APPEND TYPES_PUBLIC_HEADERS
   "bad_optional_access.h"
   "optional.h"
   "span.h"
+  "variant.h"
 )
 
 
@@ -95,7 +96,19 @@ absl_library(
     bad_optional_access
 )
 
-
+# variant library
+absl_library(
+  TARGET
+    absl_variant
+  SOURCES
+    "bad_variant_access.h" "bad_variant_access.cc" "variant.h" "internal/variant.h"
+  PUBLIC_LIBRARIES
+    absl::base absl::meta absl::utility
+  PRIVATE_COMPILE_FLAGS
+    ${ABSL_EXCEPTIONS_FLAG}
+  EXPORT_NAME
+    variant
+)
 
 #
 ## TESTS
diff --git a/absl/types/any.h b/absl/types/any.h
index 760a160e7562..68bc288bd5dd 100644
--- a/absl/types/any.h
+++ b/absl/types/any.h
@@ -172,7 +172,9 @@ const ValueType* any_cast(const any* operand) noexcept;
 template <typename ValueType>
 ValueType* any_cast(any* operand) noexcept;
 
-// any
+// -----------------------------------------------------------------------------
+// absl::any
+// -----------------------------------------------------------------------------
 //
 // An `absl::any` object provides the facility to either store an instance of a
 // type, known as the "contained object", or no value. An `absl::any` is used to
diff --git a/absl/types/bad_any_cast.h b/absl/types/bad_any_cast.h
index 8ffbe4bff473..3b963077d417 100644
--- a/absl/types/bad_any_cast.h
+++ b/absl/types/bad_any_cast.h
@@ -1,4 +1,4 @@
-// Copyright 2017 The Abseil Authors.
+// Copyright 2018 The Abseil Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -11,6 +11,12 @@
 // 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.
+//
+// -----------------------------------------------------------------------------
+// bad_any_cast.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::bad_any_cast` type.
 
 #ifndef ABSL_TYPES_BAD_ANY_CAST_H_
 #define ABSL_TYPES_BAD_ANY_CAST_H_
@@ -19,21 +25,28 @@
 
 namespace absl {
 
-////////////////////////
-// [any.bad_any_cast] //
-////////////////////////
-
-// Objects of type bad_any_cast are thrown by a failed any_cast.
+// -----------------------------------------------------------------------------
+// bad_any_cast
+// -----------------------------------------------------------------------------
+//
+// An `absl::bad_any_cast` type is an exception type that is thrown when
+// failing to successfully cast the return value of an `absl::any` object.
+//
+// Example:
+//
+//   auto a = absl::any(65);
+//   absl::any_cast<int>(a);         // 65
+//   try {
+//     absl::any_cast<char>(a);
+//   } catch(const absl::bad_any_cast& e) {
+//     std::cout << "Bad any cast: " << e.what() << '\n';
+//   }
 class bad_any_cast : public std::bad_cast {
  public:
   ~bad_any_cast() override;
   const char* what() const noexcept override;
 };
 
-//////////////////////////////////////////////
-// Implementation-details beyond this point //
-//////////////////////////////////////////////
-
 namespace any_internal {
 
 [[noreturn]] void ThrowBadAnyCast();
diff --git a/absl/types/bad_optional_access.h b/absl/types/bad_optional_access.h
index c4c74447d493..e9aa8b83eda1 100644
--- a/absl/types/bad_optional_access.h
+++ b/absl/types/bad_optional_access.h
@@ -1,4 +1,4 @@
-// Copyright 2017 The Abseil Authors.
+// Copyright 2018 The Abseil Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -11,6 +11,12 @@
 // 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.
+//
+// -----------------------------------------------------------------------------
+// bad_optional_access.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::bad_optional_access` type.
 
 #ifndef ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
 #define ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
@@ -19,6 +25,23 @@
 
 namespace absl {
 
+// -----------------------------------------------------------------------------
+// bad_optional_access
+// -----------------------------------------------------------------------------
+//
+// An `absl::bad_optional_access` type is an exception type that is thrown when
+// attempting to access an `absl::optional` object that does not contain a
+// value.
+//
+// Example:
+//
+//   absl::optional<int> o;
+//
+//   try {
+//     int n = o.value();
+//   } catch(const absl::bad_optional_access& e) {
+//     std::cout << "Bad optional access: " << e.what() << '\n';
+//   }
 class bad_optional_access : public std::exception {
  public:
   bad_optional_access() = default;
diff --git a/absl/types/bad_variant_access.cc b/absl/types/bad_variant_access.cc
new file mode 100644
index 000000000000..817fd78909a5
--- /dev/null
+++ b/absl/types/bad_variant_access.cc
@@ -0,0 +1,58 @@
+// Copyright 2017 The Abseil Authors.
+//
+// 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 "absl/types/bad_variant_access.h"
+
+#include <cstdlib>
+#include <stdexcept>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+
+namespace absl {
+
+//////////////////////////
+// [variant.bad.access] //
+//////////////////////////
+
+bad_variant_access::~bad_variant_access() = default;
+
+const char* bad_variant_access::what() const noexcept {
+  return "Bad variant access";
+}
+
+namespace variant_internal {
+
+void ThrowBadVariantAccess() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  throw bad_variant_access();
+#else
+  ABSL_RAW_LOG(FATAL, "Bad variant access");
+  abort();  // TODO(calabrese) Remove once RAW_LOG FATAL is noreturn.
+#endif
+}
+
+void Rethrow() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  throw;
+#else
+  ABSL_RAW_LOG(FATAL,
+               "Internal error in absl::variant implementation. Attempted to "
+               "rethrow an exception when building with exceptions disabled.");
+  abort();  // TODO(calabrese) Remove once RAW_LOG FATAL is noreturn.
+#endif
+}
+
+}  // namespace variant_internal
+}  // namespace absl
diff --git a/absl/types/bad_variant_access.h b/absl/types/bad_variant_access.h
new file mode 100644
index 000000000000..67abe7136b7b
--- /dev/null
+++ b/absl/types/bad_variant_access.h
@@ -0,0 +1,64 @@
+// Copyright 2018 The Abseil Authors.
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+// bad_variant_access.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::bad_variant_access` type.
+
+#ifndef ABSL_TYPES_BAD_VARIANT_ACCESS_H_
+#define ABSL_TYPES_BAD_VARIANT_ACCESS_H_
+
+#include <stdexcept>
+
+namespace absl {
+
+// -----------------------------------------------------------------------------
+// bad_variant_access
+// -----------------------------------------------------------------------------
+//
+// An `absl::bad_variant_access` type is an exception type that is thrown in
+// the following cases:
+//
+//   * Calling `absl::get(absl::variant) with an index or type that does not
+//     match the currently selected alternative type
+//   * Calling `absl::visit on an `absl::variant` that is in the
+//     `variant::valueless_by_exception` state.
+//
+// Example:
+//
+//   absl::variant<int, std::string> v;
+//   v = 1;
+//   try {
+//     absl::get<std::string>(v);
+//   } catch(const absl::bad_variant_access& e) {
+//     std::cout << "Bad variant access: " << e.what() << '\n';
+//   }
+class bad_variant_access : public std::exception {
+ public:
+  bad_variant_access() noexcept = default;
+  ~bad_variant_access() override;
+  const char* what() const noexcept override;
+};
+
+namespace variant_internal {
+
+[[noreturn]] void ThrowBadVariantAccess();
+[[noreturn]] void Rethrow();
+
+}  // namespace variant_internal
+}  // namespace absl
+
+#endif  // ABSL_TYPES_BAD_VARIANT_ACCESS_H_
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
new file mode 100644
index 000000000000..61c56ddf4e8f
--- /dev/null
+++ b/absl/types/internal/variant.h
@@ -0,0 +1,1387 @@
+// Copyright 2017 The Abseil Authors.
+//
+// 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.
+//
+// Implementation details of absl/types/variant.h, pulled into a
+// separate file to avoid cluttering the top of the API header with
+// implementation details.
+
+#ifndef ABSL_TYPES_variant_internal_H_
+#define ABSL_TYPES_variant_internal_H_
+
+#include <cstddef>
+#include <memory>
+#include <stdexcept>
+#include <tuple>
+#include <type_traits>
+
+#include "absl/base/internal/identity.h"
+#include "absl/base/internal/inline_variable.h"
+#include "absl/base/internal/invoke.h"
+#include "absl/base/optimization.h"
+#include "absl/meta/type_traits.h"
+#include "absl/types/bad_variant_access.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+
+template <class... Types>
+class variant;
+
+ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
+
+template <class T>
+struct variant_size;
+
+template <std::size_t I, class T>
+struct variant_alternative;
+
+namespace variant_internal {
+
+// NOTE: See specializations below for details.
+template <std::size_t I, class T>
+struct VariantAlternativeSfinae {};
+
+// Requires: I < variant_size_v<T>.
+//
+// Value: The Ith type of Types...
+template <std::size_t I, class T0, class... Tn>
+struct VariantAlternativeSfinae<I, variant<T0, Tn...>>
+    : VariantAlternativeSfinae<I - 1, variant<Tn...>> {};
+
+// Value: T0
+template <class T0, class... Ts>
+struct VariantAlternativeSfinae<0, variant<T0, Ts...>> {
+  using type = T0;
+};
+
+template <std::size_t I, class T>
+using VariantAlternativeSfinaeT = typename VariantAlternativeSfinae<I, T>::type;
+
+// NOTE: Requires T to be a reference type.
+template <class T, class U>
+struct GiveQualsTo;
+
+template <class T, class U>
+struct GiveQualsTo<T&, U> {
+  using type = U&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<T&&, U> {
+  using type = U&&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<const T&, U> {
+  using type = const U&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<const T&&, U> {
+  using type = const U&&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<volatile T&, U> {
+  using type = volatile U&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<volatile T&&, U> {
+  using type = volatile U&&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<volatile const T&, U> {
+  using type = volatile const U&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<volatile const T&&, U> {
+  using type = volatile const U&&;
+};
+
+template <class T, class U>
+using GiveQualsToT = typename GiveQualsTo<T, U>::type;
+
+// Convenience alias, since size_t integral_constant is used a lot in this file.
+template <std::size_t I>
+using SizeT = std::integral_constant<std::size_t, I>;
+
+template <class Variant, class T, class = void>
+struct IndexOfConstructedType {};
+
+template <std::size_t I, class Variant>
+struct VariantAccessResultImpl;
+
+template <std::size_t I, template <class...> class Variantemplate, class... T>
+struct VariantAccessResultImpl<I, Variantemplate<T...>&> {
+  using type = typename absl::variant_alternative<I, variant<T...>>::type&;
+};
+
+template <std::size_t I, template <class...> class Variantemplate, class... T>
+struct VariantAccessResultImpl<I, const Variantemplate<T...>&> {
+  using type =
+      const typename absl::variant_alternative<I, variant<T...>>::type&;
+};
+
+template <std::size_t I, template <class...> class Variantemplate, class... T>
+struct VariantAccessResultImpl<I, Variantemplate<T...>&&> {
+  using type = typename absl::variant_alternative<I, variant<T...>>::type&&;
+};
+
+template <std::size_t I, template <class...> class Variantemplate, class... T>
+struct VariantAccessResultImpl<I, const Variantemplate<T...>&&> {
+  using type =
+      const typename absl::variant_alternative<I, variant<T...>>::type&&;
+};
+
+template <std::size_t I, class Variant>
+using VariantAccessResult =
+    typename VariantAccessResultImpl<I, Variant&&>::type;
+
+// NOTE: This is used instead of std::array to reduce instantiation overhead.
+template <class T, std::size_t Size>
+struct SimpleArray {
+  static_assert(Size != 0, "");
+  T value[Size];
+};
+
+template <class T>
+struct AccessedType {
+  using type = T;
+};
+
+template <class T>
+using AccessedTypeT = typename AccessedType<T>::type;
+
+template <class T, std::size_t Size>
+struct AccessedType<SimpleArray<T, Size>> {
+  using type = AccessedTypeT<T>;
+};
+
+template <class T>
+constexpr T AccessSimpleArray(const T& value) {
+  return value;
+}
+
+template <class T, std::size_t Size, class... SizeT>
+constexpr AccessedTypeT<T> AccessSimpleArray(const SimpleArray<T, Size>& table,
+                                             std::size_t head_index,
+                                             SizeT... tail_indices) {
+  return AccessSimpleArray(table.value[head_index], tail_indices...);
+}
+
+// Note: Intentionally is an alias.
+template <class T>
+using AlwaysZero = SizeT<0>;
+
+template <class Op, class... Vs>
+struct VisitIndicesResultImpl {
+  using type = absl::result_of_t<Op(AlwaysZero<Vs>...)>;
+};
+
+template <class Op, class... Vs>
+using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type;
+
+template <class ReturnType, class FunctionObject, class EndIndices,
+          std::size_t... BoundIndices>
+struct MakeVisitationMatrix;
+
+template <class ReturnType, class FunctionObject, std::size_t... Indices>
+constexpr ReturnType call_with_indices(FunctionObject&& function) {
+  static_assert(
+      std::is_same<ReturnType, decltype(std::declval<FunctionObject>()(
+                                   SizeT<Indices>()...))>::value,
+      "Not all visitation overloads have the same return type.");
+  return absl::forward<FunctionObject>(function)(SizeT<Indices>()...);
+}
+
+template <class ReturnType, class FunctionObject, std::size_t... BoundIndices>
+struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>,
+                            BoundIndices...> {
+  using ResultType = ReturnType (*)(FunctionObject&&);
+  static constexpr ResultType Run() {
+    return &call_with_indices<ReturnType, FunctionObject,
+                              (BoundIndices - 1)...>;
+  }
+};
+
+template <class ReturnType, class FunctionObject, class EndIndices,
+          class CurrIndices, std::size_t... BoundIndices>
+struct MakeVisitationMatrixImpl;
+
+template <class ReturnType, class FunctionObject, std::size_t... EndIndices,
+          std::size_t... CurrIndices, std::size_t... BoundIndices>
+struct MakeVisitationMatrixImpl<
+    ReturnType, FunctionObject, index_sequence<EndIndices...>,
+    index_sequence<CurrIndices...>, BoundIndices...> {
+  using ResultType = SimpleArray<
+      typename MakeVisitationMatrix<ReturnType, FunctionObject,
+                                    index_sequence<EndIndices...>>::ResultType,
+      sizeof...(CurrIndices)>;
+
+  static constexpr ResultType Run() {
+    return {{MakeVisitationMatrix<ReturnType, FunctionObject,
+                                  index_sequence<EndIndices...>,
+                                  BoundIndices..., CurrIndices>::Run()...}};
+  }
+};
+
+template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex,
+          std::size_t... TailEndIndices, std::size_t... BoundIndices>
+struct MakeVisitationMatrix<ReturnType, FunctionObject,
+                            index_sequence<HeadEndIndex, TailEndIndices...>,
+                            BoundIndices...>
+    : MakeVisitationMatrixImpl<
+          ReturnType, FunctionObject, index_sequence<TailEndIndices...>,
+          absl::make_index_sequence<HeadEndIndex>, BoundIndices...> {};
+
+template <std::size_t... EndIndices, class Op, class... SizeT>
+VisitIndicesResultT<Op, SizeT...> visit_indices(Op&& op, SizeT... indices) {
+  return AccessSimpleArray(
+      MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op,
+                           index_sequence<(EndIndices + 1)...>>::Run(),
+      (indices + 1)...)(absl::forward<Op>(op));
+}
+
+template <class ReturnType>
+[[noreturn]] ReturnType TypedThrowBadVariantAccess() {
+  absl::variant_internal::ThrowBadVariantAccess();
+}
+
+// Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast`
+// below is returning the address of a temporary or local object.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4172)
+#endif  // _MSC_VER
+
+// TODO(calabrese) std::launder
+// TODO(calabrese) constexpr
+template <class Self, std::size_t I>
+VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) {
+  return reinterpret_cast<VariantAccessResult<I, Self>>(self);
+}
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif  // _MSC_VER
+
+template <class T>
+void DeducedDestroy(T& self) {  // NOLINT
+  self.~T();
+}
+
+// NOTE: This type exists as a single entity for variant and its bases to
+// befriend. It contains helper functionality that manipulates the state of the
+// variant, such as the implementation of things like assignment and emplace
+// operations.
+struct VariantCoreAccess {
+  template <class VariantType>
+  static typename VariantType::Variant& Derived(VariantType& self) {  // NOLINT
+    return static_cast<typename VariantType::Variant&>(self);
+  }
+
+  template <class VariantType>
+  static const typename VariantType::Variant& Derived(
+      const VariantType& self) {  // NOLINT
+    return static_cast<const typename VariantType::Variant&>(self);
+  }
+
+  template <class VariantType>
+  static void Destroy(VariantType& self) {  // NOLINT
+    Derived(self).destroy();
+    self.index_ = absl::variant_npos;
+  }
+
+  template <class Variant>
+  static void SetIndex(Variant& self, std::size_t i) {  // NOLINT
+    self.index_ = i;
+  }
+
+  template <class Variant>
+  static void InitFrom(Variant& self, Variant&& other) {  // NOLINT
+    variant_internal::visit_indices<absl::variant_size<Variant>::value>(
+        InitFromVisitor<Variant, Variant&&>{&self,
+                                            std::forward<Variant>(other)},
+        other.index());
+    self.index_ = other.index();
+  }
+
+  template <std::size_t I, class Variant>
+  static VariantAccessResult<I, Variant> Access(Variant&& self) {
+    if (ABSL_PREDICT_FALSE(self.index_ != I)) {
+      TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>();
+    }
+
+    // This cast instead of invocation of AccessUnion with an rvalue is a
+    // workaround for msvc. Without this there is a runtime failure when dealing
+    // with rvalues.
+    // TODO(calabrese) Reduce test case and find a simpler workaround.
+    return static_cast<VariantAccessResult<I, Variant>>(
+        variant_internal::AccessUnion(self.state_, SizeT<I>()));
+  }
+
+  // The implementation of the move-assignment operation for a variant.
+  template <class VType>
+  struct MoveAssignVisitor {
+    using DerivedType = typename VType::Variant;
+    template <std::size_t NewIndex>
+    void operator()(SizeT<NewIndex> /*new_i*/) const {
+      if (left->index_ == NewIndex) {
+        Access<NewIndex>(*left) = std::move(Access<NewIndex>(*right));
+      } else {
+        Derived(*left).template emplace<NewIndex>(
+            std::move(Access<NewIndex>(*right)));
+      }
+    }
+
+    void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
+      Destroy(*left);
+    }
+
+    VType* left;
+    VType* right;
+  };
+
+  template <class VType>
+  static MoveAssignVisitor<VType> MakeMoveAssignVisitor(VType* left,
+                                                        VType* other) {
+    return {left, other};
+  }
+
+  // The implementation of the assignment operation for a variant.
+  template <class VType>
+  struct CopyAssignVisitor {
+    using DerivedType = typename VType::Variant;
+    template <std::size_t NewIndex>
+    void operator()(SizeT<NewIndex> /*new_i*/) const {
+      using New =
+          typename absl::variant_alternative<NewIndex, DerivedType>::type;
+
+      if (left->index_ == NewIndex) {
+        Access<NewIndex>(*left) = Access<NewIndex>(*right);
+      } else if (std::is_nothrow_copy_constructible<New>::value ||
+                 !std::is_nothrow_move_constructible<New>::value) {
+        Derived(*left).template emplace<NewIndex>(Access<NewIndex>(*right));
+      } else {
+        Derived(*left) = DerivedType(Derived(*right));
+      }
+    }
+
+    void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
+      Destroy(*left);
+    }
+
+    VType* left;
+    const VType* right;
+  };
+
+  template <class VType>
+  static CopyAssignVisitor<VType> MakeCopyAssignVisitor(VType* left,
+                                                        const VType& other) {
+    return {left, &other};
+  }
+
+  // The implementation of conversion-assignment operations for variant.
+  template <class Left, class QualifiedNew>
+  struct ConversionAssignVisitor {
+    using NewIndex =
+        variant_internal::IndexOfConstructedType<Left, QualifiedNew>;
+
+    void operator()(SizeT<NewIndex::value> /*old_i*/
+                    ) const {
+      Access<NewIndex::value>(*left) = absl::forward<QualifiedNew>(other);
+    }
+
+    template <std::size_t OldIndex>
+    void operator()(SizeT<OldIndex> /*old_i*/
+                    ) const {
+      using New =
+          typename absl::variant_alternative<NewIndex::value, Left>::type;
+      if (std::is_nothrow_constructible<New, QualifiedNew>::value ||
+          !std::is_nothrow_move_constructible<New>::value) {
+        left->template emplace<NewIndex::value>(
+            absl::forward<QualifiedNew>(other));
+      } else {
+        // the standard says "equivalent to
+        // operator=(variant(std::forward<T>(t)))", but we use `emplace` here
+        // because the variant's move assignment operator could be deleted.
+        left->template emplace<NewIndex::value>(
+            New(absl::forward<QualifiedNew>(other)));
+      }
+    }
+
+    Left* left;
+    QualifiedNew&& other;
+  };
+
+  template <class Left, class QualifiedNew>
+  static ConversionAssignVisitor<Left, QualifiedNew>
+  MakeConversionAssignVisitor(Left* left, QualifiedNew&& qual) {
+    return {left, absl::forward<QualifiedNew>(qual)};
+  }
+
+  // Backend for operations for `emplace()` which destructs `*self` then
+  // construct a new alternative with `Args...`.
+  template <std::size_t NewIndex, class Self, class... Args>
+  static typename absl::variant_alternative<NewIndex, Self>::type& Replace(
+      Self* self, Args&&... args) {
+    Destroy(*self);
+    using New = typename absl::variant_alternative<NewIndex, Self>::type;
+    New* const result = ::new (static_cast<void*>(&self->state_))
+        New(absl::forward<Args>(args)...);
+    self->index_ = NewIndex;
+    return *result;
+  }
+
+  template <class LeftVariant, class QualifiedRightVariant>
+  struct InitFromVisitor {
+    template <std::size_t NewIndex>
+    void operator()(SizeT<NewIndex> /*new_i*/) const {
+      using Alternative =
+          typename variant_alternative<NewIndex, LeftVariant>::type;
+      ::new (static_cast<void*>(&left->state_)) Alternative(
+          Access<NewIndex>(std::forward<QualifiedRightVariant>(right)));
+    }
+
+    void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
+      // This space intentionally left blank.
+    }
+    LeftVariant* left;
+    QualifiedRightVariant&& right;
+  };
+};
+
+template <class Expected, class... T>
+struct IndexOfImpl;
+
+template <class Expected>
+struct IndexOfImpl<Expected> {
+  using IndexFromEnd = SizeT<0>;
+  using MatchedIndexFromEnd = IndexFromEnd;
+  using MultipleMatches = std::false_type;
+};
+
+template <class Expected, class Head, class... Tail>
+struct IndexOfImpl<Expected, Head, Tail...> : IndexOfImpl<Expected, Tail...> {
+  using IndexFromEnd =
+      SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
+};
+
+template <class Expected, class... Tail>
+struct IndexOfImpl<Expected, Expected, Tail...>
+    : IndexOfImpl<Expected, Tail...> {
+  using IndexFromEnd =
+      SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
+  using MatchedIndexFromEnd = IndexFromEnd;
+  using MultipleMatches = std::integral_constant<
+      bool, IndexOfImpl<Expected, Tail...>::MatchedIndexFromEnd::value != 0>;
+};
+
+template <class Expected, class... Types>
+struct IndexOfMeta {
+  using Results = IndexOfImpl<Expected, Types...>;
+  static_assert(!Results::MultipleMatches::value,
+                "Attempted to access a variant by specifying a type that "
+                "matches more than one alternative.");
+  static_assert(Results::MatchedIndexFromEnd::value != 0,
+                "Attempted to access a variant by specifying a type that does "
+                "not match any alternative.");
+  using type = SizeT<sizeof...(Types) - Results::MatchedIndexFromEnd::value>;
+};
+
+template <class Expected, class... Types>
+using IndexOf = typename IndexOfMeta<Expected, Types...>::type;
+
+template <class Variant, class T, std::size_t CurrIndex>
+struct UnambiguousIndexOfImpl;
+
+// Terminating case encountered once we've checked all of the alternatives
+template <class T, std::size_t CurrIndex>
+struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {};
+
+// Case where T is not Head
+template <class Head, class... Tail, class T, std::size_t CurrIndex>
+struct UnambiguousIndexOfImpl<variant<Head, Tail...>, T, CurrIndex>
+    : UnambiguousIndexOfImpl<variant<Tail...>, T, CurrIndex + 1>::type {};
+
+// Case where T is Head
+template <class Head, class... Tail, std::size_t CurrIndex>
+struct UnambiguousIndexOfImpl<variant<Head, Tail...>, Head, CurrIndex>
+    : SizeT<UnambiguousIndexOfImpl<variant<Tail...>, Head, 0>::value ==
+                    sizeof...(Tail)
+                ? CurrIndex
+                : CurrIndex + sizeof...(Tail) + 1> {};
+
+template <class Variant, class T>
+struct UnambiguousIndexOf;
+
+struct NoMatch {
+  struct type {};
+};
+
+template <class... Alts, class T>
+struct UnambiguousIndexOf<variant<Alts...>, T>
+    : std::conditional<UnambiguousIndexOfImpl<variant<Alts...>, T, 0>::value !=
+                           sizeof...(Alts),
+                       UnambiguousIndexOfImpl<variant<Alts...>, T, 0>,
+                       NoMatch>::type::type {};
+
+template <class T, std::size_t /*Dummy*/>
+using UnambiguousTypeOfImpl = T;
+
+template <class Variant, class T>
+using UnambiguousTypeOfT =
+    UnambiguousTypeOfImpl<T, UnambiguousIndexOf<Variant, T>::value>;
+
+template <class H, class... T>
+class VariantStateBase;
+
+// This is an implementation of the "imaginary function" that is described in
+// [variant.ctor]
+// It is used in order to determine which alternative to construct during
+// initialization from some type T.
+template <class Variant, std::size_t I = 0>
+struct ImaginaryFun;
+
+template <std::size_t I>
+struct ImaginaryFun<variant<>, I> {
+  static void Run() = delete;
+};
+
+template <class H, class... T, std::size_t I>
+struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> {
+  using ImaginaryFun<variant<T...>, I + 1>::Run;
+
+  // NOTE: const& and && are used instead of by-value due to lack of guaranteed
+  // move elision of C++17. This may have other minor differences, but tests
+  // pass.
+  static SizeT<I> Run(const H&);
+  static SizeT<I> Run(H&&);
+};
+
+// The following metafunctions are used in constructor and assignment
+// constraints.
+template <class Self, class T>
+struct IsNeitherSelfNorInPlace : std::true_type {};
+
+template <class Self>
+struct IsNeitherSelfNorInPlace<Self, Self> : std::false_type {};
+
+template <class Self, class T>
+struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {};
+
+template <class Self, std::size_t I>
+struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {};
+
+template <class Variant, class T, class = void>
+struct ConversionIsPossibleImpl : std::false_type {};
+
+template <class Variant, class T>
+struct ConversionIsPossibleImpl<
+    Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
+    : std::true_type {};
+
+template <class Variant, class T>
+struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {};
+
+template <class Variant, class T>
+struct IndexOfConstructedType<
+    Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
+    : decltype(ImaginaryFun<Variant>::Run(std::declval<T>())) {};
+
+template <std::size_t... Is>
+struct ContainsVariantNPos
+    : absl::negation<std::is_same<  // NOLINT
+          absl::integer_sequence<bool, 0 <= Is...>,
+          absl::integer_sequence<bool, Is != absl::variant_npos...>>> {};
+
+template <class Op, class... QualifiedVariants>
+using RawVisitResult =
+    absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
+
+// NOTE: The spec requires that all return-paths yield the same type and is not
+// SFINAE-friendly, so we can deduce the return type by examining the first
+// result. If it's not callable, then we get an error, but are compliant and
+// fast to compile.
+// TODO(calabrese) Possibly rewrite in a way that yields better compile errors
+// at the cost of longer compile-times.
+template <class Op, class... QualifiedVariants>
+struct VisitResultImpl {
+  using type =
+      absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
+};
+
+// Done in two steps intentionally so that we don't cause substitution to fail.
+template <class Op, class... QualifiedVariants>
+using VisitResult = typename VisitResultImpl<Op, QualifiedVariants...>::type;
+
+template <class Op, class... QualifiedVariants>
+struct PerformVisitation {
+  using ReturnType = VisitResult<Op, QualifiedVariants...>;
+
+  template <std::size_t... Is>
+  constexpr ReturnType operator()(SizeT<Is>... indices) const {
+    return Run(typename ContainsVariantNPos<Is...>::type{},
+               absl::index_sequence_for<QualifiedVariants...>(), indices...);
+  }
+
+  template <std::size_t... TupIs, std::size_t... Is>
+  constexpr ReturnType Run(std::false_type /*has_valueless*/,
+                           index_sequence<TupIs...>, SizeT<Is>...) const {
+    return absl::base_internal::Invoke(
+        absl::forward<Op>(op),
+        VariantCoreAccess::Access<Is>(
+            absl::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...);
+  }
+
+  template <std::size_t... TupIs, std::size_t... Is>
+  [[noreturn]] ReturnType Run(std::true_type /*has_valueless*/,
+                              index_sequence<TupIs...>, SizeT<Is>...) const {
+    absl::variant_internal::ThrowBadVariantAccess();
+  }
+
+  // TODO(calabrese) Avoid using a tuple, which causes lots of instantiations
+  // Attempts using lambda variadic captures fail on current GCC.
+  std::tuple<QualifiedVariants&&...> variant_tup;
+  Op&& op;
+};
+
+template <class... T>
+union Union;
+
+// We want to allow for variant<> to be trivial. For that, we need the default
+// constructor to be trivial, which means we can't define it ourselves.
+// Instead, we use a non-default constructor that takes NoopConstructorTag
+// that doesn't affect the triviality of the types.
+struct NoopConstructorTag {};
+
+template <std::size_t I>
+struct EmplaceTag {};
+
+template <>
+union Union<> {
+  constexpr explicit Union(NoopConstructorTag) noexcept {}
+};
+
+// Suppress bogus warning on MSVC: MSVC complains that Union<T...> has a defined
+// deleted destructor from the `std::is_destructible` check below.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4624)
+#endif  // _MSC_VER
+
+template <class Head, class... Tail>
+union Union<Head, Tail...> {
+  using TailUnion = Union<Tail...>;
+
+  explicit constexpr Union(NoopConstructorTag /*tag*/) noexcept
+      : tail(NoopConstructorTag()) {}
+
+  template <class... P>
+  explicit constexpr Union(EmplaceTag<0>, P&&... args)
+      : head(absl::forward<P>(args)...) {}
+
+  template <std::size_t I, class... P>
+  explicit constexpr Union(EmplaceTag<I>, P&&... args)
+      : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {}
+
+  Head head;
+  TailUnion tail;
+};
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif  // _MSC_VER
+
+// TODO(calabrese) Just contain a Union in this union (certain configs fail).
+template <class... T>
+union DestructibleUnionImpl;
+
+template <>
+union DestructibleUnionImpl<> {
+  constexpr explicit DestructibleUnionImpl(NoopConstructorTag) noexcept {}
+};
+
+template <class Head, class... Tail>
+union DestructibleUnionImpl<Head, Tail...> {
+  using TailUnion = DestructibleUnionImpl<Tail...>;
+
+  explicit constexpr DestructibleUnionImpl(NoopConstructorTag /*tag*/) noexcept
+      : tail(NoopConstructorTag()) {}
+
+  template <class... P>
+  explicit constexpr DestructibleUnionImpl(EmplaceTag<0>, P&&... args)
+      : head(absl::forward<P>(args)...) {}
+
+  template <std::size_t I, class... P>
+  explicit constexpr DestructibleUnionImpl(EmplaceTag<I>, P&&... args)
+      : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {}
+
+  ~DestructibleUnionImpl() {}
+
+  Head head;
+  TailUnion tail;
+};
+
+// This union type is destructible even if one or more T are not trivially
+// destructible. In the case that all T are trivially destructible, then so is
+// this resultant type.
+template <class... T>
+using DestructibleUnion =
+    absl::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>,
+                        DestructibleUnionImpl<T...>>;
+
+// Deepest base, containing the actual union and the discriminator
+template <class H, class... T>
+class VariantStateBase {
+ protected:
+  using Variant = variant<H, T...>;
+
+  template <class LazyH = H,
+            class ConstructibleH = absl::enable_if_t<
+                std::is_default_constructible<LazyH>::value, LazyH>>
+  constexpr VariantStateBase() noexcept(
+      std::is_nothrow_default_constructible<ConstructibleH>::value)
+      : state_(EmplaceTag<0>()), index_(0) {}
+
+  template <std::size_t I, class... P>
+  explicit constexpr VariantStateBase(EmplaceTag<I> tag, P&&... args)
+      : state_(tag, absl::forward<P>(args)...), index_(I) {}
+
+  explicit constexpr VariantStateBase(NoopConstructorTag)
+      : state_(NoopConstructorTag()), index_(variant_npos) {}
+
+  void destroy() {}  // Does nothing (shadowed in child if non-trivial)
+
+  DestructibleUnion<H, T...> state_;
+  std::size_t index_;
+};
+
+using absl::internal::identity;
+
+// OverloadSet::Overload() is a unary function which is overloaded to
+// take any of the element types of the variant, by reference-to-const.
+// The return type of the overload on T is identity<T>, so that you
+// can statically determine which overload was called.
+//
+// Overload() is not defined, so it can only be called in unevaluated
+// contexts.
+template <typename... Ts>
+struct OverloadSet;
+
+template <typename T, typename... Ts>
+struct OverloadSet<T, Ts...> : OverloadSet<Ts...> {
+  using Base = OverloadSet<Ts...>;
+  static identity<T> Overload(const T&);
+  using Base::Overload;
+};
+
+template <>
+struct OverloadSet<> {
+  // For any case not handled above.
+  static void Overload(...);
+};
+
+////////////////////////////////
+// Library Fundamentals V2 TS //
+////////////////////////////////
+
+// TODO(calabrese): Consider moving this to absl/meta/type_traits.h
+
+// The following is a rough implementation of parts of the detection idiom.
+// It is used for the comparison operator checks.
+
+template <class Enabler, class To, template <class...> class Op, class... Args>
+struct is_detected_convertible_impl {
+  using type = std::false_type;
+};
+
+template <class To, template <class...> class Op, class... Args>
+struct is_detected_convertible_impl<
+    absl::enable_if_t<std::is_convertible<Op<Args...>, To>::value>, To, Op,
+    Args...> {
+  using type = std::true_type;
+};
+
+// NOTE: This differs from library fundamentals by being lazy.
+template <class To, template <class...> class Op, class... Args>
+struct is_detected_convertible
+    : is_detected_convertible_impl<void, To, Op, Args...>::type {};
+
+template <class T>
+using LessThanResult = decltype(std::declval<T>() < std::declval<T>());
+
+template <class T>
+using GreaterThanResult = decltype(std::declval<T>() > std::declval<T>());
+
+template <class T>
+using LessThanOrEqualResult = decltype(std::declval<T>() <= std::declval<T>());
+
+template <class T>
+using GreaterThanOrEqualResult =
+    decltype(std::declval<T>() >= std::declval<T>());
+
+template <class T>
+using EqualResult = decltype(std::declval<T>() == std::declval<T>());
+
+template <class T>
+using NotEqualResult = decltype(std::declval<T>() != std::declval<T>());
+
+template <class T>
+using HasLessThan = is_detected_convertible<bool, LessThanResult, T>;
+
+template <class T>
+using HasGreaterThan = is_detected_convertible<bool, GreaterThanResult, T>;
+
+template <class T>
+using HasLessThanOrEqual =
+    is_detected_convertible<bool, LessThanOrEqualResult, T>;
+
+template <class T>
+using HasGreaterThanOrEqual =
+    is_detected_convertible<bool, GreaterThanOrEqualResult, T>;
+
+template <class T>
+using HasEqual = is_detected_convertible<bool, EqualResult, T>;
+
+template <class T>
+using HasNotEqual = is_detected_convertible<bool, NotEqualResult, T>;
+
+template <class... T>
+using RequireAllHaveEqualT =
+    absl::enable_if_t<absl::conjunction<HasEqual<T>...>::value, bool>;
+
+template <class... T>
+using RequireAllHaveNotEqualT =
+    absl::enable_if_t<absl::conjunction<HasEqual<T>...>::value, bool>;
+
+template <class... T>
+using RequireAllHaveLessThanT =
+    absl::enable_if_t<absl::conjunction<HasLessThan<T>...>::value, bool>;
+
+template <class... T>
+using RequireAllHaveLessThanOrEqualT =
+    absl::enable_if_t<absl::conjunction<HasLessThan<T>...>::value, bool>;
+
+template <class... T>
+using RequireAllHaveGreaterThanOrEqualT =
+    absl::enable_if_t<absl::conjunction<HasLessThan<T>...>::value, bool>;
+
+template <class... T>
+using RequireAllHaveGreaterThanT =
+    absl::enable_if_t<absl::conjunction<HasLessThan<T>...>::value, bool>;
+
+// Helper template containing implementations details of variant that can't go
+// in the private section. For convenience, this takes the variant type as a
+// single template parameter.
+template <typename T>
+struct VariantHelper;
+
+template <typename... Ts>
+struct VariantHelper<variant<Ts...>> {
+  // Type metafunction which returns the element type selected if
+  // OverloadSet::Overload() is well-formed when called with argument type U.
+  template <typename U>
+  using BestMatch = decltype(
+      variant_internal::OverloadSet<Ts...>::Overload(std::declval<U>()));
+
+  // Type metafunction which returns true if OverloadSet::Overload() is
+  // well-formed when called with argument type U.
+  // CanAccept can't be just an alias because there is a MSVC bug on parameter
+  // pack expansion involving decltype.
+  template <typename U>
+  struct CanAccept :
+      std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
+
+  // Type metafunction which returns true if Other is an instantiation of
+  // variant, and variants's converting constructor from Other will be
+  // well-formed. We will use this to remove constructors that would be
+  // ill-formed from the overload set.
+  template <typename Other>
+  struct CanConvertFrom;
+
+  template <typename... Us>
+  struct CanConvertFrom<variant<Us...>>
+      : public absl::conjunction<CanAccept<Us>...> {};
+};
+
+// A type with nontrivial copy ctor and trivial move ctor.
+struct TrivialMoveOnly {
+  TrivialMoveOnly(TrivialMoveOnly&&) = default;
+};
+
+// Trait class to detect whether a type is trivially move constructible.
+// A union's defaulted copy/move constructor is deleted if any variant member's
+// copy/move constructor is nontrivial.
+template <typename T>
+struct IsTriviallyMoveConstructible:
+  std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
+
+// To guarantee triviality of all special-member functions that can be trivial,
+// we use a chain of conditional bases for each one.
+// The order of inheritance of bases from child to base are logically:
+//
+// variant
+// VariantCopyAssignBase
+// VariantMoveAssignBase
+// VariantCopyBase
+// VariantMoveBase
+// VariantStateBaseDestructor
+// VariantStateBase
+//
+// Note that there is a separate branch at each base that is dependent on
+// whether or not that corresponding special-member-function can be trivial in
+// the resultant variant type.
+
+template <class... T>
+class VariantStateBaseDestructorNontrivial;
+
+template <class... T>
+class VariantMoveBaseNontrivial;
+
+template <class... T>
+class VariantCopyBaseNontrivial;
+
+template <class... T>
+class VariantMoveAssignBaseNontrivial;
+
+template <class... T>
+class VariantCopyAssignBaseNontrivial;
+
+// Base that is dependent on whether or not the destructor can be trivial.
+template <class... T>
+using VariantStateBaseDestructor =
+    absl::conditional_t<std::is_destructible<Union<T...>>::value,
+                        VariantStateBase<T...>,
+                        VariantStateBaseDestructorNontrivial<T...>>;
+
+// Base that is dependent on whether or not the move-constructor can be
+// implicitly generated by the compiler (trivial or deleted).
+// Previously we were using `std::is_move_constructible<Union<T...>>` to check
+// whether all Ts have trivial move constructor, but it ran into a GCC bug:
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84866
+// So we have to use a different approach (i.e. `HasTrivialMoveConstructor`) to
+// work around the bug.
+template <class... T>
+using VariantMoveBase = absl::conditional_t<
+    absl::disjunction<
+        absl::negation<absl::conjunction<std::is_move_constructible<T>...>>,
+        absl::conjunction<IsTriviallyMoveConstructible<T>...>>::value,
+    VariantStateBaseDestructor<T...>, VariantMoveBaseNontrivial<T...>>;
+
+// Base that is dependent on whether or not the copy-constructor can be trivial.
+template <class... T>
+using VariantCopyBase = absl::conditional_t<
+    absl::disjunction<
+        absl::negation<absl::conjunction<std::is_copy_constructible<T>...>>,
+        std::is_copy_constructible<Union<T...>>>::value,
+    VariantMoveBase<T...>, VariantCopyBaseNontrivial<T...>>;
+
+// Base that is dependent on whether or not the move-assign can be trivial.
+template <class... T>
+using VariantMoveAssignBase = absl::conditional_t<
+    absl::disjunction<absl::conjunction<std::is_move_assignable<Union<T...>>,
+                                        std::is_move_constructible<Union<T...>>,
+                                        std::is_destructible<Union<T...>>>,
+                      absl::negation<absl::conjunction<
+                          std::is_move_constructible<T>...,
+                          std::is_move_assignable<T>...>>>::value,
+    VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
+
+// Base that is dependent on whether or not the copy-assign can be trivial.
+template <class... T>
+using VariantCopyAssignBase = absl::conditional_t<
+    absl::disjunction<absl::conjunction<std::is_copy_assignable<Union<T...>>,
+                                        std::is_copy_constructible<Union<T...>>,
+                                        std::is_destructible<Union<T...>>>,
+                      absl::negation<absl::conjunction<
+                          std::is_copy_constructible<T>...,
+                          std::is_copy_assignable<T>...>>>::value,
+    VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
+
+template <class... T>
+using VariantBase = VariantCopyAssignBase<T...>;
+
+template <class... T>
+class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> {
+ private:
+  using Base = VariantStateBase<T...>;
+
+ protected:
+  using Base::Base;
+
+  VariantStateBaseDestructorNontrivial() = default;
+  VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) =
+      default;
+  VariantStateBaseDestructorNontrivial(
+      const VariantStateBaseDestructorNontrivial&) = default;
+  VariantStateBaseDestructorNontrivial& operator=(
+      VariantStateBaseDestructorNontrivial&&) = default;
+  VariantStateBaseDestructorNontrivial& operator=(
+      const VariantStateBaseDestructorNontrivial&) = default;
+
+  struct Destroyer {
+    template <std::size_t I>
+    void operator()(SizeT<I> i) const {
+      using Alternative =
+          typename absl::variant_alternative<I, variant<T...>>::type;
+      variant_internal::AccessUnion(self->state_, i).~Alternative();
+    }
+
+    void operator()(SizeT<absl::variant_npos> /*i*/) const {
+      // This space intentionally left blank
+    }
+
+    VariantStateBaseDestructorNontrivial* self;
+  };
+
+  void destroy() {
+    variant_internal::visit_indices<sizeof...(T)>(Destroyer{this}, index_);
+  }
+
+  ~VariantStateBaseDestructorNontrivial() { destroy(); }
+
+ protected:
+  using Base::index_;
+  using Base::state_;
+};
+
+template <class... T>
+class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> {
+ private:
+  using Base = VariantStateBaseDestructor<T...>;
+
+ protected:
+  using Base::Base;
+
+  struct Construct {
+    template <std::size_t I>
+    void operator()(SizeT<I> i) const {
+      using Alternative =
+          typename absl::variant_alternative<I, variant<T...>>::type;
+      ::new (static_cast<void*>(&self->state_)) Alternative(
+          variant_internal::AccessUnion(absl::move(other->state_), i));
+    }
+
+    void operator()(SizeT<absl::variant_npos> /*i*/) const {}
+
+    VariantMoveBaseNontrivial* self;
+    VariantMoveBaseNontrivial* other;
+  };
+
+  VariantMoveBaseNontrivial() = default;
+  VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept(
+      absl::conjunction<std::is_nothrow_move_constructible<T>...>::value)
+      : Base(NoopConstructorTag()) {
+    variant_internal::visit_indices<sizeof...(T)>(Construct{this, &other},
+                                                  other.index_);
+    index_ = other.index_;
+  }
+
+  VariantMoveBaseNontrivial(VariantMoveBaseNontrivial const&) = default;
+
+  VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial&&) = default;
+  VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial const&) =
+      default;
+
+ protected:
+  using Base::index_;
+  using Base::state_;
+};
+
+template <class... T>
+class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> {
+ private:
+  using Base = VariantMoveBase<T...>;
+
+ protected:
+  using Base::Base;
+
+  VariantCopyBaseNontrivial() = default;
+  VariantCopyBaseNontrivial(VariantCopyBaseNontrivial&&) = default;
+
+  struct Construct {
+    template <std::size_t I>
+    void operator()(SizeT<I> i) const {
+      using Alternative =
+          typename absl::variant_alternative<I, variant<T...>>::type;
+      ::new (static_cast<void*>(&self->state_))
+          Alternative(variant_internal::AccessUnion(other->state_, i));
+    }
+
+    void operator()(SizeT<absl::variant_npos> /*i*/) const {}
+
+    VariantCopyBaseNontrivial* self;
+    const VariantCopyBaseNontrivial* other;
+  };
+
+  VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other)
+      : Base(NoopConstructorTag()) {
+    variant_internal::visit_indices<sizeof...(T)>(Construct{this, &other},
+                                                  other.index_);
+    index_ = other.index_;
+  }
+
+  VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial&&) = default;
+  VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial const&) =
+      default;
+
+ protected:
+  using Base::index_;
+  using Base::state_;
+};
+
+template <class... T>
+class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> {
+  friend struct VariantCoreAccess;
+
+ private:
+  using Base = VariantCopyBase<T...>;
+
+ protected:
+  using Base::Base;
+
+  VariantMoveAssignBaseNontrivial() = default;
+  VariantMoveAssignBaseNontrivial(VariantMoveAssignBaseNontrivial&&) = default;
+  VariantMoveAssignBaseNontrivial(const VariantMoveAssignBaseNontrivial&) =
+      default;
+  VariantMoveAssignBaseNontrivial& operator=(
+      VariantMoveAssignBaseNontrivial const&) = default;
+
+    VariantMoveAssignBaseNontrivial&
+    operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
+        absl::conjunction<std::is_nothrow_move_constructible<T>...,
+                          std::is_nothrow_move_assignable<T>...>::value) {
+      variant_internal::visit_indices<sizeof...(T)>(
+          VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
+      return *this;
+    }
+
+ protected:
+  using Base::index_;
+  using Base::state_;
+};
+
+template <class... T>
+class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> {
+  friend struct VariantCoreAccess;
+
+ private:
+  using Base = VariantMoveAssignBase<T...>;
+
+ protected:
+  using Base::Base;
+
+  VariantCopyAssignBaseNontrivial() = default;
+  VariantCopyAssignBaseNontrivial(VariantCopyAssignBaseNontrivial&&) = default;
+  VariantCopyAssignBaseNontrivial(const VariantCopyAssignBaseNontrivial&) =
+      default;
+  VariantCopyAssignBaseNontrivial& operator=(
+      VariantCopyAssignBaseNontrivial&&) = default;
+
+    VariantCopyAssignBaseNontrivial& operator=(
+        const VariantCopyAssignBaseNontrivial& other) {
+      variant_internal::visit_indices<sizeof...(T)>(
+          VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
+      return *this;
+    }
+
+ protected:
+  using Base::index_;
+  using Base::state_;
+};
+
+////////////////////////////////////////
+// Visitors for Comparison Operations //
+////////////////////////////////////////
+
+template <class... Types>
+struct EqualsOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
+    return true;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) == VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+template <class... Types>
+struct NotEqualsOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
+    return false;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) != VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+template <class... Types>
+struct LessThanOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
+    return false;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) < VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+template <class... Types>
+struct GreaterThanOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
+    return false;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) > VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+template <class... Types>
+struct LessThanOrEqualsOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
+    return true;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) <= VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+template <class... Types>
+struct GreaterThanOrEqualsOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
+    return true;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+// Precondition: v.index() == w.index();
+template <class... Types>
+struct SwapSameIndex {
+  variant<Types...>* v;
+  variant<Types...>* w;
+  template <std::size_t I>
+  void operator()(SizeT<I>) const {
+    using std::swap;
+    swap(VariantCoreAccess::Access<I>(*v), VariantCoreAccess::Access<I>(*w));
+  }
+
+  void operator()(SizeT<variant_npos>) const {}
+};
+
+// TODO(calabrese) do this from a different namespace for proper adl usage
+template <class... Types>
+struct Swap {
+  variant<Types...>* v;
+  variant<Types...>* w;
+
+  void generic_swap() const {
+    variant<Types...> tmp(std::move(*w));
+    VariantCoreAccess::Destroy(*w);
+    VariantCoreAccess::InitFrom(*w, std::move(*v));
+    VariantCoreAccess::Destroy(*v);
+    VariantCoreAccess::InitFrom(*v, std::move(tmp));
+  }
+
+  void operator()(SizeT<absl::variant_npos> /*w_i*/) const {
+    if (!v->valueless_by_exception()) {
+      generic_swap();
+    }
+  }
+
+  template <std::size_t Wi>
+  void operator()(SizeT<Wi> /*w_i*/) {
+    if (v->index() == Wi) {
+      visit_indices<sizeof...(Types)>(SwapSameIndex<Types...>{v, w}, Wi);
+    } else {
+      generic_swap();
+    }
+  }
+};
+
+template <typename Variant, typename = void, typename... Ts>
+struct VariantHashBase {
+  VariantHashBase() = delete;
+  VariantHashBase(const VariantHashBase&) = delete;
+  VariantHashBase(VariantHashBase&&) = delete;
+  VariantHashBase& operator=(const VariantHashBase&) = delete;
+  VariantHashBase& operator=(VariantHashBase&&) = delete;
+};
+
+struct VariantHashVisitor {
+  template <typename T>
+  size_t operator()(const T& t) {
+    return std::hash<T>{}(t);
+  }
+};
+
+template <typename Variant, typename... Ts>
+struct VariantHashBase<Variant,
+                       absl::enable_if_t<absl::conjunction<
+                           type_traits_internal::IsHashEnabled<Ts>...>::value>,
+                       Ts...> {
+  using argument_type = Variant;
+  using result_type = size_t;
+  size_t operator()(const Variant& var) const {
+    if (var.valueless_by_exception()) {
+      return 239799884;
+    }
+    size_t result =
+        variant_internal::visit_indices<variant_size<Variant>::value>(
+            PerformVisitation<VariantHashVisitor, const Variant&>{
+                std::forward_as_tuple(var), VariantHashVisitor{}},
+            var.index());
+    // Combine the index and the hash result in order to distinguish
+    // std::variant<int, int> holding the same value as different alternative.
+    return result ^ var.index();
+  }
+};
+
+}  // namespace variant_internal
+}  // namespace absl
+
+#endif  // ABSL_TYPES_variant_internal_H_
diff --git a/absl/types/optional.h b/absl/types/optional.h
index 9313fd23c0bb..581321dc37a1 100644
--- a/absl/types/optional.h
+++ b/absl/types/optional.h
@@ -1,4 +1,3 @@
-//
 // Copyright 2017 The Abseil Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -94,7 +93,9 @@ using std::nullopt;
 
 namespace absl {
 
-// optional
+// -----------------------------------------------------------------------------
+// absl::optional
+// -----------------------------------------------------------------------------
 //
 // A value of type `absl::optional<T>` holds either a value of `T` or an
 // "empty" value.  When it holds a value of `T`, it stores it as a direct
diff --git a/absl/types/variant.h b/absl/types/variant.h
new file mode 100644
index 000000000000..52a311e37d3b
--- /dev/null
+++ b/absl/types/variant.h
@@ -0,0 +1,838 @@
+// Copyright 2018 The Abseil Authors.
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+// variant.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines an `absl::variant` type for holding a type-safe
+// value of some prescribed set of types (noted as alternative types), and
+// associated functions for managing variants.
+//
+// The `absl::variant` type is a form of type-safe union. An `absl::variant`
+// should always hold a value of one of its alternative types (except in the
+// "valueless by exception state" -- see below). A default-constructed
+// `absl::variant` will hold the value of its first alternative type, provided
+// it is default-constructable.
+//
+// In exceptional cases due to error, an `absl::variant` can hold no
+// value (known as a "valueless by exception" state), though this is not the
+// norm.
+//
+// As with `absl::optional`, an `absl::variant` -- when it holds a value --
+// allocates a value of that type directly within the `variant` itself; it
+// cannot hold a reference, array, or the type `void`; it can, however, hold a
+// pointer to externally managed memory.
+//
+// `absl::variant` is a C++11 compatible version of the C++17 `std::variant`
+// abstraction and is designed to be a drop-in replacement for code compliant
+// with C++17.
+
+#ifndef ABSL_TYPES_VARIANT_H_
+#define ABSL_TYPES_VARIANT_H_
+
+#include "absl/base/config.h"
+#include "absl/utility/utility.h"
+
+#ifdef ABSL_HAVE_STD_VARIANT
+
+#include <variant>
+
+namespace absl {
+using std::bad_variant_access;
+using std::get;
+using std::get_if;
+using std::holds_alternative;
+using std::monostate;
+using std::variant;
+using std::variant_alternative;
+using std::variant_alternative_t;
+using std::variant_npos;
+using std::variant_size;
+using std::variant_size_v;
+using std::visit;
+}  // namespace absl
+
+#else  // ABSL_HAVE_STD_VARIANT
+
+#include <functional>
+#include <new>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/macros.h"
+#include "absl/base/port.h"
+#include "absl/meta/type_traits.h"
+#include "absl/types/internal/variant.h"
+
+namespace absl {
+
+// -----------------------------------------------------------------------------
+// absl::variant
+// -----------------------------------------------------------------------------
+//
+// An 'absl::variant` type is a form of type-safe union. An `absl::variant` --
+// except in exceptional cases -- always holds a value of one of its alternative
+// types.
+//
+// Example:
+//
+//   // Construct a variant that holds either an integer or a std::string and
+//   // assign it to a std::string.
+//   absl::variant<int, std::string> v = std::string("abc");
+//
+//   // A default-contructed variant will hold a value-initialized value of
+//   // the first alternative type.
+//   auto a = absl::variant<int, std::string>();   // Holds an int of value '0'.
+//
+//   // variants are assignable.
+//
+//   // copy assignment
+//   auto v1 = absl::variant<int, std::string>("abc");
+//   auto v2 = absl::variant<int, std::string>(10);
+//   v2 = v1;  // copy assign
+//
+//   // move assignment
+//   auto v1 = absl::variant<int, std::string>("abc");
+//   v1 = absl::variant<int, std::string>(10);
+//
+//   // assignment through type conversion
+//   a = 128;         // variant contains int
+//   a = "128";       // variant contains std::string
+//
+// An `absl::variant` holding a value of one of its alternative types `T` holds
+// an allocation of `T` directly within the variant itself. An `absl::variant`
+// is not allowed to allocate additional storage, such as dynamic memory, to
+// allocate the contained value. The contained value shall be allocated in a
+// region of the variant storage suitably aligned for all alternative types.
+template <typename... Ts>
+class variant;
+
+// swap()
+//
+// Swaps two `absl::variant` values. This function is equivalent to `v.swap(w)`
+// where `v` and `w` are `absl::variant` types.
+//
+// Note that this function requires all alternative types to be both swappable
+// and move-constructible, because any two variants may refer to either the same
+// type (in which case, they will be swapped) or to two different types (in
+// which case the values will need to be moved).
+//
+template <typename... Ts>
+void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
+  v.swap(w);
+}
+
+// variant_size
+//
+// Returns the number of alterative types available for a given `absl::variant`
+// type as a compile-time constant expression. As this is a class template, it
+// is not generally useful for accessing the number of alternative types of
+// any given `absl::variant` instance.
+//
+// Example:
+//
+//   auto a = absl::variant<int, std::string>;
+//   constexpr int num_types =
+//       absl::variant_size<absl::variant<int, std::string>>();
+//
+//   // You can also use the member constant `value`.
+//   constexpr int num_types =
+//       absl::variant_size<absl::variant<int, std::string>>::value;
+//
+//   // `absl::variant_size` is more valuable for use in generic code:
+//   template <typename Variant>
+//   constexpr bool IsVariantMultivalue() {
+//       return absl::variant_size<Variant>() > 1;
+//   }
+//
+// Note that the set of cv-qualified specializations of `variant_size` are
+// provided to ensure that those specializations compile (especially when passed
+// within template logic).
+template <class T>
+struct variant_size;
+
+template <class... Ts>
+struct variant_size<variant<Ts...>>
+    : std::integral_constant<std::size_t, sizeof...(Ts)> {};
+
+// Specialization of `variant_size` for const qualified variants.
+template <class T>
+struct variant_size<const T> : variant_size<T>::type {};
+
+// Specialization of `variant_size` for volatile qualified variants.
+template <class T>
+struct variant_size<volatile T> : variant_size<T>::type {};
+
+// Specialization of `variant_size` for const volatile qualified variants.
+template <class T>
+struct variant_size<const volatile T> : variant_size<T>::type {};
+
+// variant_alternative
+//
+// Returns the alternative type for a given `absl::variant` at the passed
+// index value as a compile-time constant expression. As this is a class
+// template resulting in a type, it is not useful for access of the run-time
+// value of any given `absl::variant` variable.
+//
+// Example:
+//
+//   // The type of the 0th alternative is "int".
+//   using alternative_type_0
+//     = absl::variant_alternative<0, absl::variant<int, std::string>>::type;
+//
+//   static_assert(std::is_same<alternative_type_0, int>::value, "");
+//
+//   // `absl::variant_alternative` is more valuable for use in generic code:
+//   template <typename Variant>
+//   constexpr bool IsFirstElementTrivial() {
+//       return std::is_trivial_v<variant_alternative<0, Variant>::type>;
+//   }
+//
+// Note that the set of cv-qualified specializations of `variant_alternative`
+// are provided to ensure that those specializations compile (especially when
+// passed within template logic).
+template <std::size_t I, class T>
+struct variant_alternative;
+
+template <std::size_t I, class... Types>
+struct variant_alternative<I, variant<Types...>> {
+  using type =
+      variant_internal::VariantAlternativeSfinaeT<I, variant<Types...>>;
+};
+
+// Specialization of `variant_alternative` for const qualified variants.
+template <std::size_t I, class T>
+struct variant_alternative<I, const T> {
+  using type = const typename variant_alternative<I, T>::type;
+};
+
+// Specialization of `variant_alternative` for volatile qualified variants.
+template <std::size_t I, class T>
+struct variant_alternative<I, volatile T> {
+  using type = volatile typename variant_alternative<I, T>::type;
+};
+
+// Specialization of `variant_alternative` for const volatile qualified
+// variants.
+template <std::size_t I, class T>
+struct variant_alternative<I, const volatile T> {
+  using type = const volatile typename variant_alternative<I, T>::type;
+};
+
+// Template type alias for variant_alternative<I, T>::type.
+//
+// Example:
+//
+//   using alternative_type_0
+//     = absl::variant_alternative_t<0, absl::variant<int, std::string>>;
+//   static_assert(std::is_same<alternative_type_0, int>::value, "");
+template <std::size_t I, class T>
+using variant_alternative_t = typename variant_alternative<I, T>::type;
+
+// holds_alternative()
+//
+// Checks whether the given variant currently holds a given alternative type,
+// returning `true` if so.
+//
+// Example:
+//
+//   absl::variant<int, std::string> bar = 42;
+//   if (absl::holds_alternative<int>(foo)) {
+//       std::cout << "The variant holds an integer";
+//   }
+template <class T, class... Types>
+constexpr bool holds_alternative(const variant<Types...>& v) noexcept {
+  static_assert(
+      variant_internal::UnambiguousIndexOfImpl<variant<Types...>, T,
+                                               0>::value != sizeof...(Types),
+      "The type T must occur exactly once in Types...");
+  return v.index() ==
+         variant_internal::UnambiguousIndexOf<variant<Types...>, T>::value;
+}
+
+// get()
+//
+// Returns a reference to the value currently within a given variant, using
+// either a unique alternative type amongst the variant's set of alternative
+// types, or the variant's index value. Attempting to get a variant's value
+// using a type that is not unique within the variant's set of alternative types
+// is a compile-time error. If the index of the alternative being specified is
+// different from the index of the alternative that is currently stored, throws
+// `absl::bad_variant_access`.
+//
+// Example:
+//
+//   auto a = absl::variant<int, std::string>;
+//
+//   // Get the value by type (if unique).
+//   int i = absl::get<int>(a);
+//
+//   auto b = absl::variant<int, int>;
+//
+//   // Getting the value by a type that is not unique is ill-formed.
+//   int j = absl::get<int>(b);     // Compile Error!
+//
+//   // Getting value by index not ambiguous and allowed.
+//   int k = absl::get<1>(b);
+
+// Overload for getting a variant's lvalue by type.
+template <class T, class... Types>
+constexpr T& get(variant<Types...>& v) {  // NOLINT
+  return variant_internal::VariantCoreAccess::Access<
+      variant_internal::IndexOf<T, Types...>::value>(v);
+}
+
+// Overload for getting a variant's rvalue by type.
+// Note: `absl::move()` is required to allow use of constexpr in C++11.
+template <class T, class... Types>
+constexpr T&& get(variant<Types...>&& v) {
+  return variant_internal::VariantCoreAccess::Access<
+      variant_internal::IndexOf<T, Types...>::value>(absl::move(v));
+}
+
+// Overload for getting a variant's const lvalue by type.
+template <class T, class... Types>
+constexpr const T& get(const variant<Types...>& v) {
+  return variant_internal::VariantCoreAccess::Access<
+      variant_internal::IndexOf<T, Types...>::value>(v);
+}
+
+// Overload for getting a variant's const rvalue by type.
+// Note: `absl::move()` is required to allow use of constexpr in C++11.
+template <class T, class... Types>
+constexpr const T&& get(const variant<Types...>&& v) {
+  return variant_internal::VariantCoreAccess::Access<
+      variant_internal::IndexOf<T, Types...>::value>(absl::move(v));
+}
+
+// Overload for getting a variant's lvalue by index.
+template <std::size_t I, class... Types>
+constexpr variant_alternative_t<I, variant<Types...>>& get(
+    variant<Types...>& v) {  // NOLINT
+  return variant_internal::VariantCoreAccess::Access<I>(v);
+}
+
+// Overload for getting a variant's rvalue by index.
+// Note: `absl::move()` is required to allow use of constexpr in C++11.
+template <std::size_t I, class... Types>
+constexpr variant_alternative_t<I, variant<Types...>>&& get(
+    variant<Types...>&& v) {
+  return variant_internal::VariantCoreAccess::Access<I>(absl::move(v));
+}
+
+// Overload for getting a variant's const lvalue by index.
+template <std::size_t I, class... Types>
+constexpr const variant_alternative_t<I, variant<Types...>>& get(
+    const variant<Types...>& v) {
+  return variant_internal::VariantCoreAccess::Access<I>(v);
+}
+
+// Overload for getting a variant's const rvalue by index.
+// Note: `absl::move()` is required to allow use of constexpr in C++11.
+template <std::size_t I, class... Types>
+constexpr const variant_alternative_t<I, variant<Types...>>&& get(
+    const variant<Types...>&& v) {
+  return variant_internal::VariantCoreAccess::Access<I>(absl::move(v));
+}
+
+// get_if()
+//
+// Returns a pointer to the value currently stored within a given variant, if
+// present, using either a unique alternative type amonst the variant's set of
+// alternative types, or the variant's index value. If such a value does not
+// exist, returns `nullptr`.
+//
+// As with `get`, attempting to get a variant's value using a type that is not
+// unique within the variant's set of alternative types is a compile-time error.
+
+// Overload for getting a pointer to the value stored in the given variant by
+// index.
+template <std::size_t I, class... Types>
+constexpr absl::add_pointer_t<variant_alternative_t<I, variant<Types...>>>
+get_if(variant<Types...>* v) noexcept {
+  return (v != nullptr && v->index() == I) ? std::addressof(absl::get<I>(*v))
+                                           : nullptr;
+}
+
+// Overload for getting a pointer to the const value stored in the given
+// variant by index.
+template <std::size_t I, class... Types>
+constexpr absl::add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
+get_if(const variant<Types...>* v) noexcept {
+  return (v != nullptr && v->index() == I) ? std::addressof(absl::get<I>(*v))
+                                           : nullptr;
+}
+
+// Overload for getting a pointer to the value stored in the given variant by
+// type.
+template <class T, class... Types>
+constexpr absl::add_pointer_t<T> get_if(variant<Types...>* v) noexcept {
+  return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v);
+}
+
+// Overload for getting a pointer to the const value stored in the given variant
+// by type.
+template <class T, class... Types>
+constexpr absl::add_pointer_t<const T> get_if(
+    const variant<Types...>* v) noexcept {
+  return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v);
+}
+
+// visit()
+//
+// Calls a provided functor on a given set of variants. `absl::visit()` is
+// commonly used to conditionally inspect the state of a given variant (or set
+// of variants).
+// Requires: The expression in the Effects: element shall be a valid expression
+// of the same type and value category, for all combinations of alternative
+// types of all variants. Otherwise, the program is ill-formed.
+//
+// Example:
+//
+//   // Define a visitor functor
+//   struct GetVariant {
+//       template<typename T>
+//       void operator()(const T& i) const {
+//         std::cout << "The variant's value is: " << i;
+//       }
+//   };
+//
+//   // Declare our variant, and call `absl::visit()` on it.
+//   std::variant<int, std::string> foo = std::string("foo");
+//   GetVariant visitor;
+//   std::visit(visitor, foo);  // Prints `The variant's value is: foo'
+template <typename Visitor, typename... Variants>
+variant_internal::VisitResult<Visitor, Variants...> visit(Visitor&& vis,
+                                                          Variants&&... vars) {
+  return variant_internal::visit_indices<
+      variant_size<absl::decay_t<Variants>>::value...>(
+      variant_internal::PerformVisitation<Visitor, Variants...>{
+          std::forward_as_tuple(absl::forward<Variants>(vars)...),
+          absl::forward<Visitor>(vis)},
+      vars.index()...);
+}
+
+// monostate
+//
+// The monostate class serves as a first alternative type for a variant for
+// which the first variant type is otherwise not default-constructible.
+struct monostate {};
+
+// `absl::monostate` Relational Operators
+
+constexpr bool operator<(monostate, monostate) noexcept { return false; }
+constexpr bool operator>(monostate, monostate) noexcept { return false; }
+constexpr bool operator<=(monostate, monostate) noexcept { return true; }
+constexpr bool operator>=(monostate, monostate) noexcept { return true; }
+constexpr bool operator==(monostate, monostate) noexcept { return true; }
+constexpr bool operator!=(monostate, monostate) noexcept { return false; }
+
+
+//------------------------------------------------------------------------------
+// `absl::variant` Template Definition
+//------------------------------------------------------------------------------
+template <typename T0, typename... Tn>
+class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
+  static_assert(absl::conjunction<std::is_object<T0>, std::is_object<Tn>...,
+                                  absl::negation<std::is_array<T0>>,
+                                  absl::negation<std::is_array<Tn>>...,
+                                  std::is_nothrow_destructible<T0>,
+                                  std::is_nothrow_destructible<Tn>...>::value,
+                "Attempted to instantiate a variant with an unsupported type.");
+
+  friend struct variant_internal::VariantCoreAccess;
+
+ private:
+  using Base = variant_internal::VariantBase<T0, Tn...>;
+
+ public:
+  // Constructors
+
+  // Constructs a variant holding a default-initialized value of the first
+  // alternative type.
+  constexpr variant() /*noexcept(see 111above)*/ = default;
+
+  // Copy constructor, standard semantics
+  variant(const variant& other) = default;
+
+  // Move constructor, standard semantics
+  variant(variant&& other) /*noexcept(see above)*/ = default;
+
+  // Constructs a variant of an alternative type specified by overload
+  // resolution of the provided forwarding arguments through
+  // direct-initialization.
+  //
+  // Note: If the selected constructor is a constexpr constructor, this
+  // constructor shall be a constexpr constructor.
+  //
+  // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html
+  // has been voted passed the design phase in the C++ standard meeting in Mar
+  // 2018. It will be implemented and integrated into `absl::variant`.
+  template <
+      class T,
+      std::size_t I = std::enable_if<
+          variant_internal::IsNeitherSelfNorInPlace<variant,
+                                                    absl::decay_t<T>>::value,
+          variant_internal::IndexOfConstructedType<variant, T>>::type::value,
+      class Tj = absl::variant_alternative_t<I, variant>,
+      absl::enable_if_t<std::is_constructible<Tj, T>::value>* =
+          nullptr>
+  constexpr variant(T&& t) noexcept(std::is_nothrow_constructible<Tj, T>::value)
+      : Base(variant_internal::EmplaceTag<I>(), absl::forward<T>(t)) {}
+
+  // Constructs a variant of an alternative type from the arguments through
+  // direct-initialization.
+  //
+  // Note: If the selected constructor is a constexpr constructor, this
+  // constructor shall be a constexpr constructor.
+  template <class T, class... Args,
+            typename std::enable_if<std::is_constructible<
+                variant_internal::UnambiguousTypeOfT<variant, T>,
+                Args...>::value>::type* = nullptr>
+  constexpr explicit variant(in_place_type_t<T>, Args&&... args)
+      : Base(variant_internal::EmplaceTag<
+                 variant_internal::UnambiguousIndexOf<variant, T>::value>(),
+             absl::forward<Args>(args)...) {}
+
+  // Constructs a variant of an alternative type from an initializer list
+  // and other arguments through direct-initialization.
+  //
+  // Note: If the selected constructor is a constexpr constructor, this
+  // constructor shall be a constexpr constructor.
+  template <class T, class U, class... Args,
+            typename std::enable_if<std::is_constructible<
+                variant_internal::UnambiguousTypeOfT<variant, T>,
+                std::initializer_list<U>&, Args...>::value>::type* = nullptr>
+  constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U> il,
+                             Args&&... args)
+      : Base(variant_internal::EmplaceTag<
+                 variant_internal::UnambiguousIndexOf<variant, T>::value>(),
+             il, absl::forward<Args>(args)...) {}
+
+  // Constructs a variant of an alternative type from a provided index,
+  // through value-initialization using the provided forwarded arguments.
+  template <std::size_t I, class... Args,
+            typename std::enable_if<std::is_constructible<
+                variant_internal::VariantAlternativeSfinaeT<I, variant>,
+                Args...>::value>::type* = nullptr>
+  constexpr explicit variant(in_place_index_t<I>, Args&&... args)
+      : Base(variant_internal::EmplaceTag<I>(), absl::forward<Args>(args)...) {}
+
+  // Constructs a variant of an alternative type from a provided index,
+  // through value-initialization of an initializer list and the provided
+  // forwarded arguments.
+  template <std::size_t I, class U, class... Args,
+            typename std::enable_if<std::is_constructible<
+                variant_internal::VariantAlternativeSfinaeT<I, variant>,
+                std::initializer_list<U>&, Args...>::value>::type* = nullptr>
+  constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U> il,
+                             Args&&... args)
+      : Base(variant_internal::EmplaceTag<I>(), il,
+             absl::forward<Args>(args)...) {}
+
+  // Destructors
+
+  // Destroys the variant's currently contained value, provided that
+  // `absl::valueless_by_exception()` is false.
+  ~variant() = default;
+
+  // Assignment Operators
+
+  // Copy assignement operator
+  variant& operator=(const variant& other) = default;
+
+  // Move assignment operator
+  variant& operator=(variant&& other) /*noexcept(see above)*/ = default;
+
+  // Converting assignment operator
+  //
+  // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html
+  // has been voted passed the design phase in the C++ standard meeting in Mar
+  // 2018. It will be implemented and integrated into `absl::variant`.
+  template <
+      class T,
+      std::size_t I = std::enable_if<
+          !std::is_same<absl::decay_t<T>, variant>::value,
+          variant_internal::IndexOfConstructedType<variant, T>>::type::value,
+      class Tj = absl::variant_alternative_t<I, variant>,
+      typename std::enable_if<std::is_assignable<Tj&, T>::value &&
+                              std::is_constructible<Tj, T>::value>::type* =
+          nullptr>
+  variant& operator=(T&& t) noexcept(
+      std::is_nothrow_assignable<Tj&, T>::value&&
+          std::is_nothrow_constructible<Tj, T>::value) {
+    variant_internal::visit_indices<sizeof...(Tn) + 1>(
+        variant_internal::VariantCoreAccess::MakeConversionAssignVisitor(
+            this, absl::forward<T>(t)),
+        index());
+
+    return *this;
+  }
+
+
+  // emplace() Functions
+
+  // Constructs a value of the given alternative type T within the variant.
+  //
+  // Example:
+  //
+  //   absl::variant<std::vector<int>, int, std::string> v;
+  //   v.emplace<int>(99);
+  //   v.emplace<std::string>("abc");
+  template <
+      class T, class... Args,
+      typename std::enable_if<std::is_constructible<
+          absl::variant_alternative_t<
+              variant_internal::UnambiguousIndexOf<variant, T>::value, variant>,
+          Args...>::value>::type* = nullptr>
+  T& emplace(Args&&... args) {
+    return variant_internal::VariantCoreAccess::Replace<
+        variant_internal::UnambiguousIndexOf<variant, T>::value>(
+        this, absl::forward<Args>(args)...);
+  }
+
+  // Constructs a value of the given alternative type T within the variant using
+  // an initializer list.
+  //
+  // Example:
+  //
+  //   absl::variant<std::vector<int>, int, std::string> v;
+  //   v.emplace<std::vector<int>>({0, 1, 2});
+  template <
+      class T, class U, class... Args,
+      typename std::enable_if<std::is_constructible<
+          absl::variant_alternative_t<
+              variant_internal::UnambiguousIndexOf<variant, T>::value, variant>,
+          std::initializer_list<U>&, Args...>::value>::type* = nullptr>
+  T& emplace(std::initializer_list<U> il, Args&&... args) {
+    return variant_internal::VariantCoreAccess::Replace<
+        variant_internal::UnambiguousIndexOf<variant, T>::value>(
+        this, il, absl::forward<Args>(args)...);
+  }
+
+  // Destroys the current value of the variant (provided that
+  // `absl::valueless_by_exception()` is false, and constructs a new value at
+  // the given index.
+  //
+  // Example:
+  //
+  //   absl::variant<std::vector<int>, int, int> v;
+  //   v.emplace<1>(99);
+  //   v.emplace<2>(98);
+  //   v.emplace<int>(99);  // Won't compile. 'int' isn't a unique type.
+  template <std::size_t I, class... Args,
+            typename std::enable_if<
+                std::is_constructible<absl::variant_alternative_t<I, variant>,
+                                      Args...>::value>::type* = nullptr>
+  absl::variant_alternative_t<I, variant>& emplace(Args&&... args) {
+    return variant_internal::VariantCoreAccess::Replace<I>(
+        this, absl::forward<Args>(args)...);
+  }
+
+  // Destroys the current value of the variant (provided that
+  // `absl::valueless_by_exception()` is false, and constructs a new value at
+  // the given index using an initializer list and the provided arguments.
+  //
+  // Example:
+  //
+  //   absl::variant<std::vector<int>, int, int> v;
+  //   v.emplace<0>({0, 1, 2});
+  template <std::size_t I, class U, class... Args,
+            typename std::enable_if<std::is_constructible<
+                absl::variant_alternative_t<I, variant>,
+                std::initializer_list<U>&, Args...>::value>::type* = nullptr>
+  absl::variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il,
+                                                   Args&&... args) {
+    return variant_internal::VariantCoreAccess::Replace<I>(
+        this, il, absl::forward<Args>(args)...);
+  }
+
+  // variant::valueless_by_exception()
+  //
+  // Returns false if and only if the variant currently holds a valid value.
+  constexpr bool valueless_by_exception() const noexcept {
+    return this->index_ == absl::variant_npos;
+  }
+
+  // variant::index()
+  //
+  // Returns the index value of the variant's currently selected alternative
+  // type.
+  constexpr std::size_t index() const noexcept { return this->index_; }
+
+  // variant::swap()
+  //
+  // Swaps the values of two variant objects.
+  //
+  // TODO(calabrese)
+  //   `variant::swap()` and `swap()` rely on `std::is_(nothrow)_swappable()`
+  //   which is introduced in C++17. So we assume `is_swappable()` is always
+  //   true and `is_nothrow_swappable()` is same as `std::is_trivial()`.
+  void swap(variant& rhs) noexcept(
+      absl::conjunction<std::is_trivial<T0>, std::is_trivial<Tn>...>::value) {
+    return variant_internal::visit_indices<sizeof...(Tn) + 1>(
+        variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
+  }
+};
+
+// We need a valid declaration of variant<> for SFINAE and overload resolution
+// to work properly above, but we don't need a full declaration since this type
+// will never be constructed. This declaration, though incomplete, suffices.
+template <>
+class variant<>;
+
+//------------------------------------------------------------------------------
+// Relational Operators
+//------------------------------------------------------------------------------
+//
+// If neither operand is in the `variant::valueless_by_exception` state:
+//
+//   * If the index of both variants is the same, the relational operator
+//     returns the result of the corresponding relational operator for the
+//     corresponding alternative type.
+//   * If the index of both variants is not the same, the relational operator
+//     returns the result of that operation applied to the value of the left
+//     operand's index and the value of the right operand's index.
+//   * If at least one operand is in the valueless_by_exception state:
+//     - A variant in the valueless_by_exception state is only considered equal
+//       to another variant in the valueless_by_exception state.
+//     - If exactly one operand is in the valueless_by_exception state, the
+//       variant in the valueless_by_exception state is less than the variant
+//       that is not in the valueless_by_exception state.
+//
+// Note: The value 1 is added to each index in the relational comparisons such
+// that the index corresponding to the valueless_by_exception state wraps around
+// to 0 (the lowest value for the index type), and the remaining indices stay in
+// the same relative order.
+
+// Equal-to operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveEqualT<Types...> operator==(
+    const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() == b.index()) &&
+         variant_internal::visit_indices<sizeof...(Types)>(
+             variant_internal::EqualsOp<Types...>{&a, &b}, a.index());
+}
+
+// Not equal operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveNotEqualT<Types...> operator!=(
+    const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() != b.index()) ||
+         variant_internal::visit_indices<sizeof...(Types)>(
+             variant_internal::NotEqualsOp<Types...>{&a, &b}, a.index());
+}
+
+// Less-than operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveLessThanT<Types...> operator<(
+    const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() != b.index())
+             ? (a.index() + 1) < (b.index() + 1)
+             : variant_internal::visit_indices<sizeof...(Types)>(
+                   variant_internal::LessThanOp<Types...>{&a, &b}, a.index());
+}
+
+// Greater-than operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveGreaterThanT<Types...> operator>(
+    const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() != b.index())
+             ? (a.index() + 1) > (b.index() + 1)
+             : variant_internal::visit_indices<sizeof...(Types)>(
+                   variant_internal::GreaterThanOp<Types...>{&a, &b},
+                   a.index());
+}
+
+// Less-than or equal-to operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveLessThanOrEqualT<Types...> operator<=(
+    const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() != b.index())
+             ? (a.index() + 1) < (b.index() + 1)
+             : variant_internal::visit_indices<sizeof...(Types)>(
+                   variant_internal::LessThanOrEqualsOp<Types...>{&a, &b},
+                   a.index());
+}
+
+// Greater-than or equal-to operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveGreaterThanOrEqualT<Types...>
+operator>=(const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() != b.index())
+             ? (a.index() + 1) > (b.index() + 1)
+             : variant_internal::visit_indices<sizeof...(Types)>(
+                   variant_internal::GreaterThanOrEqualsOp<Types...>{&a, &b},
+                   a.index());
+}
+
+}  // namespace absl
+
+namespace std {
+
+// hash()
+template <>  // NOLINT
+struct hash<absl::monostate> {
+  std::size_t operator()(absl::monostate) const { return 0; }
+};
+
+template <class... T>  // NOLINT
+struct hash<absl::variant<T...>>
+    : absl::variant_internal::VariantHashBase<absl::variant<T...>, void,
+                                              absl::remove_const_t<T>...> {};
+
+}  // namespace std
+
+#endif  // ABSL_HAVE_STD_VARIANT
+
+namespace absl {
+namespace variant_internal {
+
+// Helper visitor for converting a variant<Ts...>` into another type (mostly
+// variant) that can be constructed from any type.
+template <typename To>
+struct ConversionVisitor {
+  template <typename T>
+  To operator()(T&& v) const {
+    return To(std::forward<T>(v));
+  }
+};
+
+}  // namespace variant_internal
+
+// ConvertVariantTo()
+//
+// Helper functions to convert an `absl::variant` to a variant of another set of
+// types, provided that the alternative type of the new variant type can be
+// converted from any type in the source variant.
+//
+// Example:
+//
+//   absl::variant<name1, name2, float> InternalReq(const Req&);
+//
+//   // name1 and name2 are convertible to name
+//   absl::variant<name, float> ExternalReq(const Req& req) {
+//     return absl::ConvertVariantTo<absl::variant<name, float>>(
+//              InternalReq(req));
+//   }
+template <typename To, typename Variant>
+To ConvertVariantTo(Variant&& variant) {
+  return absl::visit(variant_internal::ConversionVisitor<To>{},
+                     std::forward<Variant>(variant));
+}
+
+}  // namespace absl
+
+#endif  // ABSL_TYPES_VARIANT_H_
diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc
new file mode 100644
index 000000000000..c4676c10c62d
--- /dev/null
+++ b/absl/types/variant_test.cc
@@ -0,0 +1,2622 @@
+// Copyright 2017 The Abseil Authors.
+//
+// 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.
+
+// Unit tests for the variant template. The 'is' and 'IsEmpty' methods
+// of variant are not explicitly tested because they are used repeatedly
+// in building other tests. All other public variant methods should have
+// explicit tests.
+
+#include "absl/types/variant.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <functional>
+#include <initializer_list>
+#include <memory>
+#include <ostream>
+#include <queue>
+#include <type_traits>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/port.h"
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+
+#define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \
+  EXPECT_THROW(expr, exception_t)
+
+#else
+
+#define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \
+  EXPECT_DEATH(expr, text)
+
+#endif  // ABSL_HAVE_EXCEPTIONS
+
+#define ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(...)                 \
+  ABSL_VARIANT_TEST_EXPECT_FAIL((__VA_ARGS__), absl::bad_variant_access, \
+                                "Bad variant access")
+
+struct Hashable {};
+
+namespace std {
+template <>
+struct hash<Hashable> {
+  size_t operator()(const Hashable&);
+};
+}  // namespace std
+
+struct NonHashable {};
+
+namespace absl {
+namespace {
+
+using ::testing::DoubleEq;
+using ::testing::Pointee;
+using ::testing::VariantWith;
+
+struct MoveCanThrow {
+  MoveCanThrow() : v(0) {}
+  MoveCanThrow(int v) : v(v) {}  // NOLINT(runtime/explicit)
+  MoveCanThrow(const MoveCanThrow& other) : v(other.v) {}
+  MoveCanThrow& operator=(const MoveCanThrow& /*other*/) { return *this; }
+  int v;
+};
+
+bool operator==(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v == rhs.v; }
+bool operator!=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v != rhs.v; }
+bool operator<(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v < rhs.v; }
+bool operator<=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v <= rhs.v; }
+bool operator>=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v >= rhs.v; }
+bool operator>(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v > rhs.v; }
+
+// This helper class allows us to determine if it was swapped with std::swap()
+// or with its friend swap() function.
+struct SpecialSwap {
+  explicit SpecialSwap(int i) : i(i) {}
+  friend void swap(SpecialSwap& a, SpecialSwap& b) {
+    a.special_swap = b.special_swap = true;
+    std::swap(a.i, b.i);
+  }
+  bool operator==(SpecialSwap other) const { return i == other.i; }
+  int i;
+  bool special_swap = false;
+};
+
+struct MoveOnlyWithListConstructor {
+  MoveOnlyWithListConstructor() = default;
+  explicit MoveOnlyWithListConstructor(std::initializer_list<int> /*ilist*/,
+                                       int value)
+      : value(value) {}
+  MoveOnlyWithListConstructor(MoveOnlyWithListConstructor&&) = default;
+  MoveOnlyWithListConstructor& operator=(MoveOnlyWithListConstructor&&) =
+      default;
+
+  int value = 0;
+};
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+
+struct ConversionException {};
+
+template <class T>
+struct ExceptionOnConversion {
+  // Suppress MSVC 2017 warning "noreturn function has a non-void return type".
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4646)
+#endif  // _MSC_VER
+
+  [[noreturn]] operator T() const {  // NOLINT(runtime/explicit)
+    throw ConversionException();
+  }
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif  // _MSC_VER
+};
+
+// Forces a variant into the valueless by exception state.
+template <class H, class... T>
+void ToValuelessByException(absl::variant<H, T...>& v) {  // NOLINT
+  try {
+    v.template emplace<0>(ExceptionOnConversion<H>());
+  } catch (ConversionException& /*e*/) {
+    // This space intentionally left blank.
+  }
+}
+
+#endif  // ABSL_HAVE_EXCEPTIONS
+
+// An indexed sequence of distinct structures holding a single
+// value of type T
+template<typename T, size_t N>
+struct ValueHolder {
+  explicit ValueHolder(const T& x) : value(x) {}
+  typedef T value_type;
+  value_type value;
+  static const size_t kIndex = N;
+};
+template<typename T, size_t N>
+const size_t ValueHolder<T, N>::kIndex;
+
+// The following three functions make ValueHolder compatible with
+// EXPECT_EQ and EXPECT_NE
+template<typename T, size_t N>
+inline bool operator==(const ValueHolder<T, N>& left,
+                       const ValueHolder<T, N>& right) {
+  return left.value == right.value;
+}
+
+template<typename T, size_t N>
+inline bool operator!=(const ValueHolder<T, N>& left,
+                       const ValueHolder<T, N>& right) {
+  return left.value != right.value;
+}
+
+template<typename T, size_t N>
+inline std::ostream& operator<<(
+    std::ostream& stream, const ValueHolder<T, N>& object) {
+  return stream << object.value;
+}
+
+// Makes a variant holding twelve uniquely typed T wrappers.
+template<typename T>
+struct VariantFactory {
+  typedef variant<ValueHolder<T, 1>, ValueHolder<T, 2>, ValueHolder<T, 3>,
+                  ValueHolder<T, 4>>
+      Type;
+};
+
+// A typelist in 1:1 with VariantFactory, to use type driven unit tests.
+typedef ::testing::Types<ValueHolder<size_t, 1>, ValueHolder<size_t, 2>,
+                         ValueHolder<size_t, 3>,
+                         ValueHolder<size_t, 4>> VariantTypes;
+
+// Increments the provided counter pointer in the destructor
+struct IncrementInDtor {
+  explicit IncrementInDtor(int* counter) : counter(counter) {}
+  ~IncrementInDtor() { *counter += 1; }
+  int* counter;
+};
+
+struct IncrementInDtorCopyCanThrow {
+  explicit IncrementInDtorCopyCanThrow(int* counter) : counter(counter) {}
+  IncrementInDtorCopyCanThrow(IncrementInDtorCopyCanThrow&& other) noexcept =
+      default;
+  IncrementInDtorCopyCanThrow(const IncrementInDtorCopyCanThrow& other)
+      : counter(other.counter) {}
+  IncrementInDtorCopyCanThrow& operator=(
+      IncrementInDtorCopyCanThrow&&) noexcept = default;
+  IncrementInDtorCopyCanThrow& operator=(
+      IncrementInDtorCopyCanThrow const& other) {
+    counter = other.counter;
+    return *this;
+  }
+  ~IncrementInDtorCopyCanThrow() { *counter += 1; }
+  int* counter;
+};
+
+// This is defined so operator== for ValueHolder<IncrementInDtor> will
+// return true if two IncrementInDtor objects increment the same
+// counter
+inline bool operator==(const IncrementInDtor& left,
+                       const IncrementInDtor& right) {
+  return left.counter == right.counter;
+}
+
+// This is defined so EXPECT_EQ can work with IncrementInDtor
+inline std::ostream& operator<<(
+    std::ostream& stream, const IncrementInDtor& object) {
+  return stream << object.counter;
+}
+
+// A class that can be copied, but not assigned.
+class CopyNoAssign {
+ public:
+  explicit CopyNoAssign(int value) : foo(value) {}
+  CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
+  int foo;
+ private:
+  const CopyNoAssign& operator=(const CopyNoAssign&);
+};
+
+// A class that can neither be copied nor assigned. We provide
+// overloads for the constructor with up to four parameters so we can
+// test the overloads of variant::emplace.
+class NonCopyable {
+ public:
+  NonCopyable()
+      : value(0) {}
+  explicit NonCopyable(int value1)
+      : value(value1) {}
+
+  NonCopyable(int value1, int value2)
+      : value(value1 + value2) {}
+
+  NonCopyable(int value1, int value2, int value3)
+      : value(value1 + value2 + value3) {}
+
+  NonCopyable(int value1, int value2, int value3, int value4)
+      : value(value1 + value2 + value3 + value4) {}
+  NonCopyable(const NonCopyable&) = delete;
+  NonCopyable& operator=(const NonCopyable&) = delete;
+  int value;
+};
+
+// A typed test and typed test case over the VariantTypes typelist,
+// from which we derive a number of tests that will execute for one of
+// each type.
+template <typename T>
+class VariantTypesTest : public ::testing::Test {};
+TYPED_TEST_CASE(VariantTypesTest, VariantTypes);
+
+////////////////////
+// [variant.ctor] //
+////////////////////
+
+struct NonNoexceptDefaultConstructible {
+  NonNoexceptDefaultConstructible() {}
+  int value = 5;
+};
+
+struct NonDefaultConstructible {
+  NonDefaultConstructible() = delete;
+};
+
+TEST(VariantTest, TestDefaultConstructor) {
+  {
+    using X = variant<int>;
+    constexpr variant<int> x{};
+    ASSERT_FALSE(x.valueless_by_exception());
+    ASSERT_EQ(0, x.index());
+    EXPECT_EQ(0, absl::get<0>(x));
+    EXPECT_TRUE(std::is_nothrow_default_constructible<X>::value);
+  }
+
+  {
+    using X = variant<NonNoexceptDefaultConstructible>;
+    X x{};
+    ASSERT_FALSE(x.valueless_by_exception());
+    ASSERT_EQ(0, x.index());
+    EXPECT_EQ(5, absl::get<0>(x).value);
+    EXPECT_FALSE(std::is_nothrow_default_constructible<X>::value);
+  }
+
+  {
+    using X = variant<int, NonNoexceptDefaultConstructible>;
+    X x{};
+    ASSERT_FALSE(x.valueless_by_exception());
+    ASSERT_EQ(0, x.index());
+    EXPECT_EQ(0, absl::get<0>(x));
+    EXPECT_TRUE(std::is_nothrow_default_constructible<X>::value);
+  }
+
+  {
+    using X = variant<NonNoexceptDefaultConstructible, int>;
+    X x{};
+    ASSERT_FALSE(x.valueless_by_exception());
+    ASSERT_EQ(0, x.index());
+    EXPECT_EQ(5, absl::get<0>(x).value);
+    EXPECT_FALSE(std::is_nothrow_default_constructible<X>::value);
+  }
+  EXPECT_FALSE(
+      std::is_default_constructible<variant<NonDefaultConstructible>>::value);
+  EXPECT_FALSE((std::is_default_constructible<
+                variant<NonDefaultConstructible, int>>::value));
+  EXPECT_TRUE((std::is_default_constructible<
+               variant<int, NonDefaultConstructible>>::value));
+}
+
+// Test that for each slot, copy constructing a variant with that type
+// produces a sensible object that correctly reports its type, and
+// that copies the provided value.
+TYPED_TEST(VariantTypesTest, TestCopyCtor) {
+  typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant;
+  using value_type1 = absl::variant_alternative_t<0, Variant>;
+  using value_type2 = absl::variant_alternative_t<1, Variant>;
+  using value_type3 = absl::variant_alternative_t<2, Variant>;
+  using value_type4 = absl::variant_alternative_t<3, Variant>;
+  const TypeParam value(TypeParam::kIndex);
+  Variant original(value);
+  Variant copied(original);
+  EXPECT_TRUE(absl::holds_alternative<value_type1>(copied) ||
+              TypeParam::kIndex != 1);
+  EXPECT_TRUE(absl::holds_alternative<value_type2>(copied) ||
+              TypeParam::kIndex != 2);
+  EXPECT_TRUE(absl::holds_alternative<value_type3>(copied) ||
+              TypeParam::kIndex != 3);
+  EXPECT_TRUE(absl::holds_alternative<value_type4>(copied) ||
+              TypeParam::kIndex != 4);
+  EXPECT_TRUE((absl::get_if<value_type1>(&original) ==
+               absl::get_if<value_type1>(&copied)) ||
+              TypeParam::kIndex == 1);
+  EXPECT_TRUE((absl::get_if<value_type2>(&original) ==
+               absl::get_if<value_type2>(&copied)) ||
+              TypeParam::kIndex == 2);
+  EXPECT_TRUE((absl::get_if<value_type3>(&original) ==
+               absl::get_if<value_type3>(&copied)) ||
+              TypeParam::kIndex == 3);
+  EXPECT_TRUE((absl::get_if<value_type4>(&original) ==
+               absl::get_if<value_type4>(&copied)) ||
+              TypeParam::kIndex == 4);
+  EXPECT_TRUE((absl::get_if<value_type1>(&original) ==
+               absl::get_if<value_type1>(&copied)) ||
+              TypeParam::kIndex == 1);
+  EXPECT_TRUE((absl::get_if<value_type2>(&original) ==
+               absl::get_if<value_type2>(&copied)) ||
+              TypeParam::kIndex == 2);
+  EXPECT_TRUE((absl::get_if<value_type3>(&original) ==
+               absl::get_if<value_type3>(&copied)) ||
+              TypeParam::kIndex == 3);
+  EXPECT_TRUE((absl::get_if<value_type4>(&original) ==
+               absl::get_if<value_type4>(&copied)) ||
+              TypeParam::kIndex == 4);
+  const TypeParam* ovalptr = absl::get_if<TypeParam>(&original);
+  const TypeParam* cvalptr = absl::get_if<TypeParam>(&copied);
+  ASSERT_TRUE(ovalptr != nullptr);
+  ASSERT_TRUE(cvalptr != nullptr);
+  EXPECT_EQ(*ovalptr, *cvalptr);
+  TypeParam* mutable_ovalptr = absl::get_if<TypeParam>(&original);
+  TypeParam* mutable_cvalptr = absl::get_if<TypeParam>(&copied);
+  ASSERT_TRUE(mutable_ovalptr != nullptr);
+  ASSERT_TRUE(mutable_cvalptr != nullptr);
+  EXPECT_EQ(*mutable_ovalptr, *mutable_cvalptr);
+}
+
+template <class>
+struct MoveOnly {
+  MoveOnly() = default;
+  explicit MoveOnly(int value) : value(value) {}
+  MoveOnly(MoveOnly&&) = default;
+  MoveOnly& operator=(MoveOnly&&) = default;
+  int value = 5;
+};
+
+TEST(VariantTest, TestMoveConstruct) {
+  using V = variant<MoveOnly<class A>, MoveOnly<class B>, MoveOnly<class C>>;
+
+  V v(in_place_index_t<1>{}, 10);
+  V v2 = absl::move(v);
+  EXPECT_EQ(10, absl::get<1>(v2).value);
+}
+
+// Used internally to emulate missing triviality traits for tests.
+template <class T>
+union SingleUnion {
+  T member;
+};
+
+// NOTE: These don't work with types that can't be union members.
+//       They are just for testing.
+template <class T>
+struct is_trivially_move_constructible
+    : std::is_move_constructible<SingleUnion<T>>::type {};
+
+template <class T>
+struct is_trivially_move_assignable
+    : std::is_move_assignable<SingleUnion<T>>::type {};
+
+TEST(VariantTest, NothrowMoveConstructible) {
+  // Verify that variant is nothrow move constructible iff its template
+  // arguments are.
+  using U = std::unique_ptr<int>;
+  struct E {
+    E(E&&) {}
+  };
+  static_assert(std::is_nothrow_move_constructible<variant<U>>::value, "");
+  static_assert(std::is_nothrow_move_constructible<variant<U, int>>::value, "");
+  static_assert(!std::is_nothrow_move_constructible<variant<U, E>>::value, "");
+}
+
+// Test that for each slot, constructing a variant with that type
+// produces a sensible object that correctly reports its type, and
+// that copies the provided value.
+TYPED_TEST(VariantTypesTest, TestValueCtor) {
+  typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant;
+  using value_type1 = absl::variant_alternative_t<0, Variant>;
+  using value_type2 = absl::variant_alternative_t<1, Variant>;
+  using value_type3 = absl::variant_alternative_t<2, Variant>;
+  using value_type4 = absl::variant_alternative_t<3, Variant>;
+  const TypeParam value(TypeParam::kIndex);
+  Variant v(value);
+  EXPECT_TRUE(absl::holds_alternative<value_type1>(v) ||
+              TypeParam::kIndex != 1);
+  EXPECT_TRUE(absl::holds_alternative<value_type2>(v) ||
+              TypeParam::kIndex != 2);
+  EXPECT_TRUE(absl::holds_alternative<value_type3>(v) ||
+              TypeParam::kIndex != 3);
+  EXPECT_TRUE(absl::holds_alternative<value_type4>(v) ||
+              TypeParam::kIndex != 4);
+  EXPECT_TRUE(nullptr != absl::get_if<value_type1>(&v) ||
+              TypeParam::kIndex != 1);
+  EXPECT_TRUE(nullptr != absl::get_if<value_type2>(&v) ||
+              TypeParam::kIndex != 2);
+  EXPECT_TRUE(nullptr != absl::get_if<value_type3>(&v) ||
+              TypeParam::kIndex != 3);
+  EXPECT_TRUE(nullptr != absl::get_if<value_type4>(&v) ||
+              TypeParam::kIndex != 4);
+  EXPECT_TRUE(nullptr != absl::get_if<value_type1>(&v) ||
+              TypeParam::kIndex != 1);
+  EXPECT_TRUE(nullptr != absl::get_if<value_type2>(&v) ||
+              TypeParam::kIndex != 2);
+  EXPECT_TRUE(nullptr != absl::get_if<value_type3>(&v) ||
+              TypeParam::kIndex != 3);
+  EXPECT_TRUE(nullptr != absl::get_if<value_type4>(&v) ||
+              TypeParam::kIndex != 4);
+  const TypeParam* valptr = absl::get_if<TypeParam>(&v);
+  ASSERT_TRUE(nullptr != valptr);
+  EXPECT_EQ(value.value, valptr->value);
+  const TypeParam* mutable_valptr = absl::get_if<TypeParam>(&v);
+  ASSERT_TRUE(nullptr != mutable_valptr);
+  EXPECT_EQ(value.value, mutable_valptr->value);
+}
+
+TEST(VariantTest, InPlaceType) {
+  using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
+
+  Var v1(in_place_type_t<int>(), 7);
+  ASSERT_TRUE(absl::holds_alternative<int>(v1));
+  EXPECT_EQ(7, absl::get<int>(v1));
+
+  Var v2(in_place_type_t<std::string>(), "ABC");
+  ASSERT_TRUE(absl::holds_alternative<std::string>(v2));
+  EXPECT_EQ("ABC", absl::get<std::string>(v2));
+
+  Var v3(in_place_type_t<std::string>(), "ABC", 2);
+  ASSERT_TRUE(absl::holds_alternative<std::string>(v3));
+  EXPECT_EQ("AB", absl::get<std::string>(v3));
+
+  Var v4(in_place_type_t<NonCopyable>{});
+  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v4));
+
+  Var v5(in_place_type_t<std::vector<int>>(), {1, 2, 3});
+  ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5));
+  EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
+}
+
+TEST(VariantTest, InPlaceTypeInitializerList) {
+  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+
+  Var v1(in_place_type_t<MoveOnlyWithListConstructor>(), {1, 2, 3, 4, 5}, 6);
+  ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
+  EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
+}
+
+TEST(VariantTest, InPlaceIndex) {
+  using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
+
+  Var v1(in_place_index_t<0>(), 7);
+  ASSERT_TRUE(absl::holds_alternative<int>(v1));
+  EXPECT_EQ(7, absl::get<int>(v1));
+
+  Var v2(in_place_index_t<1>(), "ABC");
+  ASSERT_TRUE(absl::holds_alternative<std::string>(v2));
+  EXPECT_EQ("ABC", absl::get<std::string>(v2));
+
+  Var v3(in_place_index_t<1>(), "ABC", 2);
+  ASSERT_TRUE(absl::holds_alternative<std::string>(v3));
+  EXPECT_EQ("AB", absl::get<std::string>(v3));
+
+  Var v4(in_place_index_t<2>{});
+  EXPECT_TRUE(absl::holds_alternative<NonCopyable>(v4));
+
+  // Verify that a variant with only non-copyables can still be constructed.
+  EXPECT_TRUE(absl::holds_alternative<NonCopyable>(
+      variant<NonCopyable>(in_place_index_t<0>{})));
+
+  Var v5(in_place_index_t<3>(), {1, 2, 3});
+  ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5));
+  EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
+}
+
+TEST(VariantTest, InPlaceIndexInitializerList) {
+  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+
+  Var v1(in_place_index_t<3>(), {1, 2, 3, 4, 5}, 6);
+  ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
+  EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
+}
+
+////////////////////
+// [variant.dtor] //
+////////////////////
+
+// Make sure that the destructor destroys the contained value
+TEST(VariantTest, TestDtor) {
+  typedef VariantFactory<IncrementInDtor>::Type Variant;
+  using value_type1 = absl::variant_alternative_t<0, Variant>;
+  using value_type2 = absl::variant_alternative_t<1, Variant>;
+  using value_type3 = absl::variant_alternative_t<2, Variant>;
+  using value_type4 = absl::variant_alternative_t<3, Variant>;
+  int counter = 0;
+  IncrementInDtor counter_adjuster(&counter);
+  EXPECT_EQ(0, counter);
+
+  value_type1 value1(counter_adjuster);
+  { Variant object(value1); }
+  EXPECT_EQ(1, counter);
+
+  value_type2 value2(counter_adjuster);
+  { Variant object(value2); }
+  EXPECT_EQ(2, counter);
+
+  value_type3 value3(counter_adjuster);
+  { Variant object(value3); }
+  EXPECT_EQ(3, counter);
+
+  value_type4 value4(counter_adjuster);
+  { Variant object(value4); }
+  EXPECT_EQ(4, counter);
+}
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+
+// Test destruction when in the valueless_by_exception state.
+TEST(VariantTest, TestDtorValuelessByException) {
+  int counter = 0;
+  IncrementInDtor counter_adjuster(&counter);
+
+  {
+    using Variant = VariantFactory<IncrementInDtor>::Type;
+
+    Variant v(in_place_index_t<0>(), counter_adjuster);
+    EXPECT_EQ(0, counter);
+
+    ToValuelessByException(v);
+    ASSERT_TRUE(v.valueless_by_exception());
+    EXPECT_EQ(1, counter);
+  }
+  EXPECT_EQ(1, counter);
+}
+
+#endif  // ABSL_HAVE_EXCEPTIONS
+
+//////////////////////
+// [variant.assign] //
+//////////////////////
+
+// Test that self-assignment doesn't destroy the current value
+TEST(VariantTest, TestSelfAssignment) {
+  typedef VariantFactory<IncrementInDtor>::Type Variant;
+  int counter = 0;
+  IncrementInDtor counter_adjuster(&counter);
+  absl::variant_alternative_t<0, Variant> value(counter_adjuster);
+  Variant object(value);
+  object.operator=(object);
+  EXPECT_EQ(0, counter);
+
+  // A std::string long enough that it's likely to defeat any inline representation
+  // optimization.
+  const std::string long_str(128, 'a');
+
+  std::string foo = long_str;
+  foo = *&foo;
+  EXPECT_EQ(long_str, foo);
+
+  variant<int, std::string> so = long_str;
+  ASSERT_EQ(1, so.index());
+  EXPECT_EQ(long_str, absl::get<1>(so));
+  so = *&so;
+
+  ASSERT_EQ(1, so.index());
+  EXPECT_EQ(long_str, absl::get<1>(so));
+}
+
+// Test that assigning a variant<..., T, ...> to a variant<..., T, ...> produces
+// a variant<..., T, ...> with the correct value.
+TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValueSameTypes) {
+  typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant;
+  const TypeParam value(TypeParam::kIndex);
+  const Variant source(value);
+  Variant target(TypeParam(value.value + 1));
+  ASSERT_TRUE(absl::holds_alternative<TypeParam>(source));
+  ASSERT_TRUE(absl::holds_alternative<TypeParam>(target));
+  ASSERT_NE(absl::get<TypeParam>(source), absl::get<TypeParam>(target));
+  target = source;
+  ASSERT_TRUE(absl::holds_alternative<TypeParam>(source));
+  ASSERT_TRUE(absl::holds_alternative<TypeParam>(target));
+  EXPECT_EQ(absl::get<TypeParam>(source), absl::get<TypeParam>(target));
+}
+
+// Test that assisnging a variant<..., T, ...> to a variant<1, ...>
+// produces a variant<..., T, ...> with the correct value.
+TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValuesVaryingSourceType) {
+  typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant;
+  using value_type1 = absl::variant_alternative_t<0, Variant>;
+  const TypeParam value(TypeParam::kIndex);
+  const Variant source(value);
+  ASSERT_TRUE(absl::holds_alternative<TypeParam>(source));
+  Variant target(value_type1(1));
+  ASSERT_TRUE(absl::holds_alternative<value_type1>(target));
+  target = source;
+  EXPECT_TRUE(absl::holds_alternative<TypeParam>(source));
+  EXPECT_TRUE(absl::holds_alternative<TypeParam>(target));
+  EXPECT_EQ(absl::get<TypeParam>(source), absl::get<TypeParam>(target));
+}
+
+// Test that assigning a variant<1, ...> to a variant<..., T, ...>
+// produces a variant<1, ...> with the correct value.
+TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValuesVaryingTargetType) {
+  typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant;
+  using value_type1 = absl::variant_alternative_t<0, Variant>;
+  const Variant source(value_type1(1));
+  ASSERT_TRUE(absl::holds_alternative<value_type1>(source));
+  const TypeParam value(TypeParam::kIndex);
+  Variant target(value);
+  ASSERT_TRUE(absl::holds_alternative<TypeParam>(target));
+  target = source;
+  EXPECT_TRUE(absl::holds_alternative<value_type1>(target));
+  EXPECT_TRUE(absl::holds_alternative<value_type1>(source));
+  EXPECT_EQ(absl::get<value_type1>(source), absl::get<value_type1>(target));
+}
+
+// Test that operator=<T> works, that assigning a new value destroys
+// the old and that assigning the new value again does not redestroy
+// the old
+TEST(VariantTest, TestAssign) {
+  typedef VariantFactory<IncrementInDtor>::Type Variant;
+  using value_type1 = absl::variant_alternative_t<0, Variant>;
+  using value_type2 = absl::variant_alternative_t<1, Variant>;
+  using value_type3 = absl::variant_alternative_t<2, Variant>;
+  using value_type4 = absl::variant_alternative_t<3, Variant>;
+
+  const int kSize = 4;
+  int counter[kSize];
+  std::unique_ptr<IncrementInDtor> counter_adjustor[kSize];
+  for (int i = 0; i != kSize; i++) {
+    counter[i] = 0;
+    counter_adjustor[i] = absl::make_unique<IncrementInDtor>(&counter[i]);
+  }
+
+  value_type1 v1(*counter_adjustor[0]);
+  value_type2 v2(*counter_adjustor[1]);
+  value_type3 v3(*counter_adjustor[2]);
+  value_type4 v4(*counter_adjustor[3]);
+
+  // Test that reassignment causes destruction of old value
+  {
+    Variant object(v1);
+    object = v2;
+    object = v3;
+    object = v4;
+    object = v1;
+  }
+
+  EXPECT_EQ(2, counter[0]);
+  EXPECT_EQ(1, counter[1]);
+  EXPECT_EQ(1, counter[2]);
+  EXPECT_EQ(1, counter[3]);
+
+  std::fill(std::begin(counter), std::end(counter), 0);
+
+  // Test that self-assignment does not cause destruction of old value
+  {
+    Variant object(v1);
+    object.operator=(object);
+    EXPECT_EQ(0, counter[0]);
+  }
+  {
+    Variant object(v2);
+    object.operator=(object);
+    EXPECT_EQ(0, counter[1]);
+  }
+  {
+    Variant object(v3);
+    object.operator=(object);
+    EXPECT_EQ(0, counter[2]);
+  }
+  {
+    Variant object(v4);
+    object.operator=(object);
+    EXPECT_EQ(0, counter[3]);
+  }
+
+  EXPECT_EQ(1, counter[0]);
+  EXPECT_EQ(1, counter[1]);
+  EXPECT_EQ(1, counter[2]);
+  EXPECT_EQ(1, counter[3]);
+}
+
+// This tests that we perform a backup if the copy-assign can throw but the move
+// cannot throw.
+TEST(VariantTest, TestBackupAssign) {
+  typedef VariantFactory<IncrementInDtorCopyCanThrow>::Type Variant;
+  using value_type1 = absl::variant_alternative_t<0, Variant>;
+  using value_type2 = absl::variant_alternative_t<1, Variant>;
+  using value_type3 = absl::variant_alternative_t<2, Variant>;
+  using value_type4 = absl::variant_alternative_t<3, Variant>;
+
+  const int kSize = 4;
+  int counter[kSize];
+  std::unique_ptr<IncrementInDtorCopyCanThrow> counter_adjustor[kSize];
+  for (int i = 0; i != kSize; i++) {
+    counter[i] = 0;
+    counter_adjustor[i].reset(new IncrementInDtorCopyCanThrow(&counter[i]));
+  }
+
+  value_type1 v1(*counter_adjustor[0]);
+  value_type2 v2(*counter_adjustor[1]);
+  value_type3 v3(*counter_adjustor[2]);
+  value_type4 v4(*counter_adjustor[3]);
+
+  // Test that reassignment causes destruction of old value
+  {
+    Variant object(v1);
+    object = v2;
+    object = v3;
+    object = v4;
+    object = v1;
+  }
+
+  // libstdc++ doesn't pass this test
+#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+  EXPECT_EQ(3, counter[0]);
+  EXPECT_EQ(2, counter[1]);
+  EXPECT_EQ(2, counter[2]);
+  EXPECT_EQ(2, counter[3]);
+#endif
+
+  std::fill(std::begin(counter), std::end(counter), 0);
+
+  // Test that self-assignment does not cause destruction of old value
+  {
+    Variant object(v1);
+    object.operator=(object);
+    EXPECT_EQ(0, counter[0]);
+  }
+  {
+    Variant object(v2);
+    object.operator=(object);
+    EXPECT_EQ(0, counter[1]);
+  }
+  {
+    Variant object(v3);
+    object.operator=(object);
+    EXPECT_EQ(0, counter[2]);
+  }
+  {
+    Variant object(v4);
+    object.operator=(object);
+    EXPECT_EQ(0, counter[3]);
+  }
+
+  EXPECT_EQ(1, counter[0]);
+  EXPECT_EQ(1, counter[1]);
+  EXPECT_EQ(1, counter[2]);
+  EXPECT_EQ(1, counter[3]);
+}
+
+///////////////////
+// [variant.mod] //
+///////////////////
+
+TEST(VariantTest, TestEmplaceBasic) {
+  using Variant = variant<int, char>;
+
+  Variant v(absl::in_place_index_t<0>{}, 0);
+
+  {
+    char& emplace_result = v.emplace<char>();
+    ASSERT_TRUE(absl::holds_alternative<char>(v));
+    EXPECT_EQ(absl::get<char>(v), 0);
+    EXPECT_EQ(&emplace_result, &absl::get<char>(v));
+  }
+
+  // Make sure that another emplace does zero-initialization
+  absl::get<char>(v) = 'a';
+  v.emplace<char>('b');
+  ASSERT_TRUE(absl::holds_alternative<char>(v));
+  EXPECT_EQ(absl::get<char>(v), 'b');
+
+  {
+    int& emplace_result = v.emplace<int>();
+    EXPECT_TRUE(absl::holds_alternative<int>(v));
+    EXPECT_EQ(absl::get<int>(v), 0);
+    EXPECT_EQ(&emplace_result, &absl::get<int>(v));
+  }
+}
+
+TEST(VariantTest, TestEmplaceInitializerList) {
+  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+
+  Var v1(absl::in_place_index_t<0>{}, 555);
+  MoveOnlyWithListConstructor& emplace_result =
+      v1.emplace<MoveOnlyWithListConstructor>({1, 2, 3, 4, 5}, 6);
+  ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
+  EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
+  EXPECT_EQ(&emplace_result, &absl::get<MoveOnlyWithListConstructor>(v1));
+}
+
+TEST(VariantTest, TestEmplaceIndex) {
+  using Variant = variant<int, char>;
+
+  Variant v(absl::in_place_index_t<0>{}, 555);
+
+  {
+    char& emplace_result = v.emplace<1>();
+    ASSERT_TRUE(absl::holds_alternative<char>(v));
+    EXPECT_EQ(absl::get<char>(v), 0);
+    EXPECT_EQ(&emplace_result, &absl::get<char>(v));
+  }
+
+  // Make sure that another emplace does zero-initialization
+  absl::get<char>(v) = 'a';
+  v.emplace<1>('b');
+  ASSERT_TRUE(absl::holds_alternative<char>(v));
+  EXPECT_EQ(absl::get<char>(v), 'b');
+
+  {
+    int& emplace_result = v.emplace<0>();
+    EXPECT_TRUE(absl::holds_alternative<int>(v));
+    EXPECT_EQ(absl::get<int>(v), 0);
+    EXPECT_EQ(&emplace_result, &absl::get<int>(v));
+  }
+}
+
+TEST(VariantTest, TestEmplaceIndexInitializerList) {
+  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+
+  Var v1(absl::in_place_index_t<0>{}, 555);
+  MoveOnlyWithListConstructor& emplace_result =
+      v1.emplace<3>({1, 2, 3, 4, 5}, 6);
+  ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
+  EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
+  EXPECT_EQ(&emplace_result, &absl::get<MoveOnlyWithListConstructor>(v1));
+}
+
+//////////////////////
+// [variant.status] //
+//////////////////////
+
+TEST(VariantTest, Index) {
+  using Var = variant<int, std::string, double>;
+
+  Var v = 1;
+  EXPECT_EQ(0, v.index());
+  v = "str";
+  EXPECT_EQ(1, v.index());
+  v = 0.;
+  EXPECT_EQ(2, v.index());
+
+  Var v2 = v;
+  EXPECT_EQ(2, v2.index());
+  v2.emplace<int>(3);
+  EXPECT_EQ(0, v2.index());
+}
+
+TEST(VariantTest, NotValuelessByException) {
+  using Var = variant<int, std::string, double>;
+
+  Var v = 1;
+  EXPECT_FALSE(v.valueless_by_exception());
+  v = "str";
+  EXPECT_FALSE(v.valueless_by_exception());
+  v = 0.;
+  EXPECT_FALSE(v.valueless_by_exception());
+
+  Var v2 = v;
+  EXPECT_FALSE(v.valueless_by_exception());
+  v2.emplace<int>(3);
+  EXPECT_FALSE(v.valueless_by_exception());
+}
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+
+TEST(VariantTest, IndexValuelessByException) {
+  using Var = variant<MoveCanThrow, std::string, double>;
+
+  Var v(absl::in_place_index_t<0>{});
+  EXPECT_EQ(0, v.index());
+  ToValuelessByException(v);
+  EXPECT_EQ(absl::variant_npos, v.index());
+  v = "str";
+  EXPECT_EQ(1, v.index());
+}
+
+TEST(VariantTest, ValuelessByException) {
+  using Var = variant<MoveCanThrow, std::string, double>;
+
+  Var v(absl::in_place_index_t<0>{});
+  EXPECT_FALSE(v.valueless_by_exception());
+  ToValuelessByException(v);
+  EXPECT_TRUE(v.valueless_by_exception());
+  v = "str";
+  EXPECT_FALSE(v.valueless_by_exception());
+}
+
+#endif  // ABSL_HAVE_EXCEPTIONS
+
+////////////////////
+// [variant.swap] //
+////////////////////
+
+TEST(VariantTest, MemberSwap) {
+  SpecialSwap v1(3);
+  SpecialSwap v2(7);
+
+  variant<SpecialSwap> a = v1, b = v2;
+
+  EXPECT_THAT(a, VariantWith<SpecialSwap>(v1));
+  EXPECT_THAT(b, VariantWith<SpecialSwap>(v2));
+
+  a.swap(b);
+  EXPECT_THAT(a, VariantWith<SpecialSwap>(v2));
+  EXPECT_THAT(b, VariantWith<SpecialSwap>(v1));
+  EXPECT_TRUE(absl::get<SpecialSwap>(a).special_swap);
+
+  using V = variant<MoveCanThrow, std::string, int>;
+  int i = 33;
+  std::string s = "abc";
+  V valueless(in_place_index_t<0>{});
+  ToValuelessByException(valueless);
+  {
+    // lhs and rhs holds different alternative
+    V lhs(i), rhs(s);
+    lhs.swap(rhs);
+    EXPECT_THAT(lhs, VariantWith<std::string>(s));
+    EXPECT_THAT(rhs, VariantWith<int>(i));
+  }
+  {
+    // lhs is valueless
+    V lhs(valueless), rhs(i);
+    lhs.swap(rhs);
+    EXPECT_THAT(lhs, VariantWith<int>(i));
+    EXPECT_TRUE(rhs.valueless_by_exception());
+  }
+  {
+    // rhs is valueless
+    V lhs(s), rhs(valueless);
+    lhs.swap(rhs);
+    EXPECT_THAT(rhs, VariantWith<std::string>(s));
+    EXPECT_TRUE(lhs.valueless_by_exception());
+  }
+  {
+    // both are valueless
+    V lhs(valueless), rhs(valueless);
+    lhs.swap(rhs);
+    EXPECT_TRUE(lhs.valueless_by_exception());
+    EXPECT_TRUE(rhs.valueless_by_exception());
+  }
+}
+
+//////////////////////
+// [variant.helper] //
+//////////////////////
+
+TEST(VariantTest, VariantSize) {
+  {
+    using Size1Variant = absl::variant<int>;
+    EXPECT_EQ(1, absl::variant_size<Size1Variant>::value);
+    EXPECT_EQ(1, absl::variant_size<const Size1Variant>::value);
+    EXPECT_EQ(1, absl::variant_size<volatile Size1Variant>::value);
+    EXPECT_EQ(1, absl::variant_size<const volatile Size1Variant>::value);
+  }
+
+  {
+    using Size3Variant = absl::variant<int, float, int>;
+    EXPECT_EQ(3, absl::variant_size<Size3Variant>::value);
+    EXPECT_EQ(3, absl::variant_size<const Size3Variant>::value);
+    EXPECT_EQ(3, absl::variant_size<volatile Size3Variant>::value);
+    EXPECT_EQ(3, absl::variant_size<const volatile Size3Variant>::value);
+  }
+}
+
+TEST(VariantTest, VariantAlternative) {
+  {
+    using V = absl::variant<float, int, const char*>;
+    EXPECT_TRUE(
+        (std::is_same<float, absl::variant_alternative_t<0, V>>::value));
+    EXPECT_TRUE((std::is_same<const float,
+                              absl::variant_alternative_t<0, const V>>::value));
+    EXPECT_TRUE(
+        (std::is_same<volatile float,
+                      absl::variant_alternative_t<0, volatile V>>::value));
+    EXPECT_TRUE((
+        std::is_same<const volatile float,
+                     absl::variant_alternative_t<0, const volatile V>>::value));
+
+    EXPECT_TRUE((std::is_same<int, absl::variant_alternative_t<1, V>>::value));
+    EXPECT_TRUE((std::is_same<const int,
+                              absl::variant_alternative_t<1, const V>>::value));
+    EXPECT_TRUE(
+        (std::is_same<volatile int,
+                      absl::variant_alternative_t<1, volatile V>>::value));
+    EXPECT_TRUE((
+        std::is_same<const volatile int,
+                     absl::variant_alternative_t<1, const volatile V>>::value));
+
+    EXPECT_TRUE(
+        (std::is_same<const char*, absl::variant_alternative_t<2, V>>::value));
+    EXPECT_TRUE((std::is_same<const char* const,
+                              absl::variant_alternative_t<2, const V>>::value));
+    EXPECT_TRUE(
+        (std::is_same<const char* volatile,
+                      absl::variant_alternative_t<2, volatile V>>::value));
+    EXPECT_TRUE((
+        std::is_same<const char* const volatile,
+                     absl::variant_alternative_t<2, const volatile V>>::value));
+  }
+
+  {
+    using V = absl::variant<float, volatile int, const char*>;
+    EXPECT_TRUE(
+        (std::is_same<float, absl::variant_alternative_t<0, V>>::value));
+    EXPECT_TRUE((std::is_same<const float,
+                              absl::variant_alternative_t<0, const V>>::value));
+    EXPECT_TRUE(
+        (std::is_same<volatile float,
+                      absl::variant_alternative_t<0, volatile V>>::value));
+    EXPECT_TRUE((
+        std::is_same<const volatile float,
+                     absl::variant_alternative_t<0, const volatile V>>::value));
+
+    EXPECT_TRUE(
+        (std::is_same<volatile int, absl::variant_alternative_t<1, V>>::value));
+    EXPECT_TRUE((std::is_same<const volatile int,
+                              absl::variant_alternative_t<1, const V>>::value));
+    EXPECT_TRUE(
+        (std::is_same<volatile int,
+                      absl::variant_alternative_t<1, volatile V>>::value));
+    EXPECT_TRUE((
+        std::is_same<const volatile int,
+                     absl::variant_alternative_t<1, const volatile V>>::value));
+
+    EXPECT_TRUE(
+        (std::is_same<const char*, absl::variant_alternative_t<2, V>>::value));
+    EXPECT_TRUE((std::is_same<const char* const,
+                              absl::variant_alternative_t<2, const V>>::value));
+    EXPECT_TRUE(
+        (std::is_same<const char* volatile,
+                      absl::variant_alternative_t<2, volatile V>>::value));
+    EXPECT_TRUE((
+        std::is_same<const char* const volatile,
+                     absl::variant_alternative_t<2, const volatile V>>::value));
+  }
+}
+
+///////////////////
+// [variant.get] //
+///////////////////
+
+TEST(VariantTest, HoldsAlternative) {
+  using Var = variant<int, std::string, double>;
+
+  Var v = 1;
+  EXPECT_TRUE(absl::holds_alternative<int>(v));
+  EXPECT_FALSE(absl::holds_alternative<std::string>(v));
+  EXPECT_FALSE(absl::holds_alternative<double>(v));
+  v = "str";
+  EXPECT_FALSE(absl::holds_alternative<int>(v));
+  EXPECT_TRUE(absl::holds_alternative<std::string>(v));
+  EXPECT_FALSE(absl::holds_alternative<double>(v));
+  v = 0.;
+  EXPECT_FALSE(absl::holds_alternative<int>(v));
+  EXPECT_FALSE(absl::holds_alternative<std::string>(v));
+  EXPECT_TRUE(absl::holds_alternative<double>(v));
+
+  Var v2 = v;
+  EXPECT_FALSE(absl::holds_alternative<int>(v2));
+  EXPECT_FALSE(absl::holds_alternative<std::string>(v2));
+  EXPECT_TRUE(absl::holds_alternative<double>(v2));
+  v2.emplace<int>(3);
+  EXPECT_TRUE(absl::holds_alternative<int>(v2));
+  EXPECT_FALSE(absl::holds_alternative<std::string>(v2));
+  EXPECT_FALSE(absl::holds_alternative<double>(v2));
+}
+
+TEST(VariantTest, GetIndex) {
+  using Var = variant<int, std::string, double, int>;
+
+  {
+    Var v(absl::in_place_index_t<0>{}, 0);
+
+    using LValueGetType = decltype(absl::get<0>(v));
+    using RValueGetType = decltype(absl::get<0>(absl::move(v)));
+
+    EXPECT_TRUE((std::is_same<LValueGetType, int&>::value));
+    EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value));
+    EXPECT_EQ(absl::get<0>(v), 0);
+    EXPECT_EQ(absl::get<0>(absl::move(v)), 0);
+
+    const Var& const_v = v;
+    using ConstLValueGetType = decltype(absl::get<0>(const_v));
+    using ConstRValueGetType = decltype(absl::get<0>(absl::move(const_v)));
+    EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value));
+    EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value));
+    EXPECT_EQ(absl::get<0>(const_v), 0);
+    EXPECT_EQ(absl::get<0>(absl::move(const_v)), 0);
+  }
+
+  {
+    Var v = std::string("Hello");
+
+    using LValueGetType = decltype(absl::get<1>(v));
+    using RValueGetType = decltype(absl::get<1>(absl::move(v)));
+
+    EXPECT_TRUE((std::is_same<LValueGetType, std::string&>::value));
+    EXPECT_TRUE((std::is_same<RValueGetType, std::string&&>::value));
+    EXPECT_EQ(absl::get<1>(v), "Hello");
+    EXPECT_EQ(absl::get<1>(absl::move(v)), "Hello");
+
+    const Var& const_v = v;
+    using ConstLValueGetType = decltype(absl::get<1>(const_v));
+    using ConstRValueGetType = decltype(absl::get<1>(absl::move(const_v)));
+    EXPECT_TRUE((std::is_same<ConstLValueGetType, const std::string&>::value));
+    EXPECT_TRUE((std::is_same<ConstRValueGetType, const std::string&&>::value));
+    EXPECT_EQ(absl::get<1>(const_v), "Hello");
+    EXPECT_EQ(absl::get<1>(absl::move(const_v)), "Hello");
+  }
+
+  {
+    Var v = 2.0;
+
+    using LValueGetType = decltype(absl::get<2>(v));
+    using RValueGetType = decltype(absl::get<2>(absl::move(v)));
+
+    EXPECT_TRUE((std::is_same<LValueGetType, double&>::value));
+    EXPECT_TRUE((std::is_same<RValueGetType, double&&>::value));
+    EXPECT_EQ(absl::get<2>(v), 2.);
+    EXPECT_EQ(absl::get<2>(absl::move(v)), 2.);
+
+    const Var& const_v = v;
+    using ConstLValueGetType = decltype(absl::get<2>(const_v));
+    using ConstRValueGetType = decltype(absl::get<2>(absl::move(const_v)));
+    EXPECT_TRUE((std::is_same<ConstLValueGetType, const double&>::value));
+    EXPECT_TRUE((std::is_same<ConstRValueGetType, const double&&>::value));
+    EXPECT_EQ(absl::get<2>(const_v), 2.);
+    EXPECT_EQ(absl::get<2>(absl::move(const_v)), 2.);
+  }
+
+  {
+    Var v(absl::in_place_index_t<0>{}, 0);
+    v.emplace<3>(1);
+
+    using LValueGetType = decltype(absl::get<3>(v));
+    using RValueGetType = decltype(absl::get<3>(absl::move(v)));
+
+    EXPECT_TRUE((std::is_same<LValueGetType, int&>::value));
+    EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value));
+    EXPECT_EQ(absl::get<3>(v), 1);
+    EXPECT_EQ(absl::get<3>(absl::move(v)), 1);
+
+    const Var& const_v = v;
+    using ConstLValueGetType = decltype(absl::get<3>(const_v));
+    using ConstRValueGetType = decltype(absl::get<3>(absl::move(const_v)));
+    EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value));
+    EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value));
+    EXPECT_EQ(absl::get<3>(const_v), 1);
+    EXPECT_EQ(absl::get<3>(absl::move(const_v)), 1);  // NOLINT
+  }
+}
+
+TEST(VariantTest, BadGetIndex) {
+  using Var = variant<int, std::string, double>;
+
+  {
+    Var v = 1;
+
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(v));
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(std::move(v)));
+
+    const Var& const_v = v;
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(const_v));
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
+        absl::get<1>(std::move(const_v)));  // NOLINT
+  }
+
+  {
+    Var v = std::string("Hello");
+
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(v));
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(std::move(v)));
+
+    const Var& const_v = v;
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(const_v));
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
+        absl::get<0>(std::move(const_v)));  // NOLINT
+  }
+}
+
+TEST(VariantTest, GetType) {
+  using Var = variant<int, std::string, double>;
+
+  {
+    Var v = 1;
+
+    using LValueGetType = decltype(absl::get<int>(v));
+    using RValueGetType = decltype(absl::get<int>(absl::move(v)));
+
+    EXPECT_TRUE((std::is_same<LValueGetType, int&>::value));
+    EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value));
+    EXPECT_EQ(absl::get<int>(v), 1);
+    EXPECT_EQ(absl::get<int>(absl::move(v)), 1);
+
+    const Var& const_v = v;
+    using ConstLValueGetType = decltype(absl::get<int>(const_v));
+    using ConstRValueGetType = decltype(absl::get<int>(absl::move(const_v)));
+    EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value));
+    EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value));
+    EXPECT_EQ(absl::get<int>(const_v), 1);
+    EXPECT_EQ(absl::get<int>(absl::move(const_v)), 1);
+  }
+
+  {
+    Var v = std::string("Hello");
+
+    using LValueGetType = decltype(absl::get<1>(v));
+    using RValueGetType = decltype(absl::get<1>(absl::move(v)));
+
+    EXPECT_TRUE((std::is_same<LValueGetType, std::string&>::value));
+    EXPECT_TRUE((std::is_same<RValueGetType, std::string&&>::value));
+    EXPECT_EQ(absl::get<std::string>(v), "Hello");
+    EXPECT_EQ(absl::get<std::string>(absl::move(v)), "Hello");
+
+    const Var& const_v = v;
+    using ConstLValueGetType = decltype(absl::get<1>(const_v));
+    using ConstRValueGetType = decltype(absl::get<1>(absl::move(const_v)));
+    EXPECT_TRUE((std::is_same<ConstLValueGetType, const std::string&>::value));
+    EXPECT_TRUE((std::is_same<ConstRValueGetType, const std::string&&>::value));
+    EXPECT_EQ(absl::get<std::string>(const_v), "Hello");
+    EXPECT_EQ(absl::get<std::string>(absl::move(const_v)), "Hello");
+  }
+
+  {
+    Var v = 2.0;
+
+    using LValueGetType = decltype(absl::get<2>(v));
+    using RValueGetType = decltype(absl::get<2>(absl::move(v)));
+
+    EXPECT_TRUE((std::is_same<LValueGetType, double&>::value));
+    EXPECT_TRUE((std::is_same<RValueGetType, double&&>::value));
+    EXPECT_EQ(absl::get<double>(v), 2.);
+    EXPECT_EQ(absl::get<double>(absl::move(v)), 2.);
+
+    const Var& const_v = v;
+    using ConstLValueGetType = decltype(absl::get<2>(const_v));
+    using ConstRValueGetType = decltype(absl::get<2>(absl::move(const_v)));
+    EXPECT_TRUE((std::is_same<ConstLValueGetType, const double&>::value));
+    EXPECT_TRUE((std::is_same<ConstRValueGetType, const double&&>::value));
+    EXPECT_EQ(absl::get<double>(const_v), 2.);
+    EXPECT_EQ(absl::get<double>(absl::move(const_v)), 2.);
+  }
+}
+
+TEST(VariantTest, BadGetType) {
+  using Var = variant<int, std::string, double>;
+
+  {
+    Var v = 1;
+
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<std::string>(v));
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
+        absl::get<std::string>(std::move(v)));
+
+    const Var& const_v = v;
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<std::string>(const_v));
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
+        absl::get<std::string>(std::move(const_v)));  // NOLINT
+  }
+
+  {
+    Var v = std::string("Hello");
+
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(v));
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(std::move(v)));
+
+    const Var& const_v = v;
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(const_v));
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
+        absl::get<int>(std::move(const_v)));  // NOLINT
+  }
+}
+
+TEST(VariantTest, GetIfIndex) {
+  using Var = variant<int, std::string, double, int>;
+
+  {
+    Var v(absl::in_place_index_t<0>{}, 0);
+    EXPECT_TRUE(noexcept(absl::get_if<0>(&v)));
+
+    {
+      auto* elem = absl::get_if<0>(&v);
+      EXPECT_TRUE((std::is_same<decltype(elem), int*>::value));
+      ASSERT_NE(elem, nullptr);
+      EXPECT_EQ(*elem, 0);
+      {
+        auto* bad_elem = absl::get_if<1>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<2>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<3>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+    }
+
+    const Var& const_v = v;
+    EXPECT_TRUE(noexcept(absl::get_if<0>(&const_v)));
+
+    {
+      auto* elem = absl::get_if<0>(&const_v);
+      EXPECT_TRUE((std::is_same<decltype(elem), const int*>::value));
+      ASSERT_NE(elem, nullptr);
+      EXPECT_EQ(*elem, 0);
+      {
+        auto* bad_elem = absl::get_if<1>(&const_v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<2>(&const_v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<3>(&const_v);
+        EXPECT_EQ(bad_elem, nullptr);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
+      }
+    }
+  }
+
+  {
+    Var v = std::string("Hello");
+    EXPECT_TRUE(noexcept(absl::get_if<1>(&v)));
+
+    {
+      auto* elem = absl::get_if<1>(&v);
+      EXPECT_TRUE((std::is_same<decltype(elem), std::string*>::value));
+      ASSERT_NE(elem, nullptr);
+      EXPECT_EQ(*elem, "Hello");
+      {
+        auto* bad_elem = absl::get_if<0>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<2>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<3>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+    }
+
+    const Var& const_v = v;
+    EXPECT_TRUE(noexcept(absl::get_if<1>(&const_v)));
+
+    {
+      auto* elem = absl::get_if<1>(&const_v);
+      EXPECT_TRUE((std::is_same<decltype(elem), const std::string*>::value));
+      ASSERT_NE(elem, nullptr);
+      EXPECT_EQ(*elem, "Hello");
+      {
+        auto* bad_elem = absl::get_if<0>(&const_v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<2>(&const_v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<3>(&const_v);
+        EXPECT_EQ(bad_elem, nullptr);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
+      }
+    }
+  }
+
+  {
+    Var v = 2.0;
+    EXPECT_TRUE(noexcept(absl::get_if<2>(&v)));
+
+    {
+      auto* elem = absl::get_if<2>(&v);
+      EXPECT_TRUE((std::is_same<decltype(elem), double*>::value));
+      ASSERT_NE(elem, nullptr);
+      EXPECT_EQ(*elem, 2.0);
+      {
+        auto* bad_elem = absl::get_if<0>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<1>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<3>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+    }
+
+    const Var& const_v = v;
+    EXPECT_TRUE(noexcept(absl::get_if<2>(&const_v)));
+
+    {
+      auto* elem = absl::get_if<2>(&const_v);
+      EXPECT_TRUE((std::is_same<decltype(elem), const double*>::value));
+      ASSERT_NE(elem, nullptr);
+      EXPECT_EQ(*elem, 2.0);
+      {
+        auto* bad_elem = absl::get_if<0>(&const_v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<1>(&const_v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<3>(&const_v);
+        EXPECT_EQ(bad_elem, nullptr);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
+      }
+    }
+  }
+
+  {
+    Var v(absl::in_place_index_t<0>{}, 0);
+    v.emplace<3>(1);
+    EXPECT_TRUE(noexcept(absl::get_if<3>(&v)));
+
+    {
+      auto* elem = absl::get_if<3>(&v);
+      EXPECT_TRUE((std::is_same<decltype(elem), int*>::value));
+      ASSERT_NE(elem, nullptr);
+      EXPECT_EQ(*elem, 1);
+      {
+        auto* bad_elem = absl::get_if<0>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<1>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<2>(&v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+    }
+
+    const Var& const_v = v;
+    EXPECT_TRUE(noexcept(absl::get_if<3>(&const_v)));
+
+    {
+      auto* elem = absl::get_if<3>(&const_v);
+      EXPECT_TRUE((std::is_same<decltype(elem), const int*>::value));
+      ASSERT_NE(elem, nullptr);
+      EXPECT_EQ(*elem, 1);
+      {
+        auto* bad_elem = absl::get_if<0>(&const_v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<1>(&const_v);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+        EXPECT_EQ(bad_elem, nullptr);
+      }
+      {
+        auto* bad_elem = absl::get_if<2>(&const_v);
+        EXPECT_EQ(bad_elem, nullptr);
+        EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value));
+      }
+    }
+  }
+}
+
+//////////////////////
+// [variant.relops] //
+//////////////////////
+
+TEST(VariantTest, OperatorEquals) {
+  variant<int, std::string> a(1), b(1);
+  EXPECT_TRUE(a == b);
+  EXPECT_TRUE(b == a);
+  EXPECT_FALSE(a != b);
+  EXPECT_FALSE(b != a);
+
+  b = "str";
+  EXPECT_FALSE(a == b);
+  EXPECT_FALSE(b == a);
+  EXPECT_TRUE(a != b);
+  EXPECT_TRUE(b != a);
+
+  b = 0;
+  EXPECT_FALSE(a == b);
+  EXPECT_FALSE(b == a);
+  EXPECT_TRUE(a != b);
+  EXPECT_TRUE(b != a);
+
+  a = b = "foo";
+  EXPECT_TRUE(a == b);
+  EXPECT_TRUE(b == a);
+  EXPECT_FALSE(a != b);
+  EXPECT_FALSE(b != a);
+
+  a = "bar";
+  EXPECT_FALSE(a == b);
+  EXPECT_FALSE(b == a);
+  EXPECT_TRUE(a != b);
+  EXPECT_TRUE(b != a);
+}
+
+TEST(VariantTest, OperatorRelational) {
+  variant<int, std::string> a(1), b(1);
+  EXPECT_FALSE(a < b);
+  EXPECT_FALSE(b < a);
+  EXPECT_FALSE(a > b);
+  EXPECT_FALSE(b > a);
+  EXPECT_TRUE(a <= b);
+  EXPECT_TRUE(b <= a);
+  EXPECT_TRUE(a >= b);
+  EXPECT_TRUE(b >= a);
+
+  b = "str";
+  EXPECT_TRUE(a < b);
+  EXPECT_FALSE(b < a);
+  EXPECT_FALSE(a > b);
+  EXPECT_TRUE(b > a);
+  EXPECT_TRUE(a <= b);
+  EXPECT_FALSE(b <= a);
+  EXPECT_FALSE(a >= b);
+  EXPECT_TRUE(b >= a);
+
+  b = 0;
+  EXPECT_FALSE(a < b);
+  EXPECT_TRUE(b < a);
+  EXPECT_TRUE(a > b);
+  EXPECT_FALSE(b > a);
+  EXPECT_FALSE(a <= b);
+  EXPECT_TRUE(b <= a);
+  EXPECT_TRUE(a >= b);
+  EXPECT_FALSE(b >= a);
+
+  a = b = "foo";
+  EXPECT_FALSE(a < b);
+  EXPECT_FALSE(b < a);
+  EXPECT_FALSE(a > b);
+  EXPECT_FALSE(b > a);
+  EXPECT_TRUE(a <= b);
+  EXPECT_TRUE(b <= a);
+  EXPECT_TRUE(a >= b);
+  EXPECT_TRUE(b >= a);
+
+  a = "bar";
+  EXPECT_TRUE(a < b);
+  EXPECT_FALSE(b < a);
+  EXPECT_FALSE(a > b);
+  EXPECT_TRUE(b > a);
+  EXPECT_TRUE(a <= b);
+  EXPECT_FALSE(b <= a);
+  EXPECT_FALSE(a >= b);
+  EXPECT_TRUE(b >= a);
+}
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+
+TEST(VariantTest, ValuelessOperatorEquals) {
+  variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"),
+      valueless(absl::in_place_index_t<0>{}),
+      other_valueless(absl::in_place_index_t<0>{});
+  ToValuelessByException(valueless);
+  ToValuelessByException(other_valueless);
+
+  EXPECT_TRUE(valueless == other_valueless);
+  EXPECT_TRUE(other_valueless == valueless);
+  EXPECT_FALSE(valueless == int_v);
+  EXPECT_FALSE(valueless == string_v);
+  EXPECT_FALSE(int_v == valueless);
+  EXPECT_FALSE(string_v == valueless);
+
+  EXPECT_FALSE(valueless != other_valueless);
+  EXPECT_FALSE(other_valueless != valueless);
+  EXPECT_TRUE(valueless != int_v);
+  EXPECT_TRUE(valueless != string_v);
+  EXPECT_TRUE(int_v != valueless);
+  EXPECT_TRUE(string_v != valueless);
+}
+
+TEST(VariantTest, ValuelessOperatorRelational) {
+  variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"),
+      valueless(absl::in_place_index_t<0>{}),
+      other_valueless(absl::in_place_index_t<0>{});
+  ToValuelessByException(valueless);
+  ToValuelessByException(other_valueless);
+
+  EXPECT_FALSE(valueless < other_valueless);
+  EXPECT_FALSE(other_valueless < valueless);
+  EXPECT_TRUE(valueless < int_v);
+  EXPECT_TRUE(valueless < string_v);
+  EXPECT_FALSE(int_v < valueless);
+  EXPECT_FALSE(string_v < valueless);
+
+  EXPECT_TRUE(valueless <= other_valueless);
+  EXPECT_TRUE(other_valueless <= valueless);
+  EXPECT_TRUE(valueless <= int_v);
+  EXPECT_TRUE(valueless <= string_v);
+  EXPECT_FALSE(int_v <= valueless);
+  EXPECT_FALSE(string_v <= valueless);
+
+  EXPECT_TRUE(valueless >= other_valueless);
+  EXPECT_TRUE(other_valueless >= valueless);
+  EXPECT_FALSE(valueless >= int_v);
+  EXPECT_FALSE(valueless >= string_v);
+  EXPECT_TRUE(int_v >= valueless);
+  EXPECT_TRUE(string_v >= valueless);
+
+  EXPECT_FALSE(valueless > other_valueless);
+  EXPECT_FALSE(other_valueless > valueless);
+  EXPECT_FALSE(valueless > int_v);
+  EXPECT_FALSE(valueless > string_v);
+  EXPECT_TRUE(int_v > valueless);
+  EXPECT_TRUE(string_v > valueless);
+}
+
+#endif
+
+/////////////////////
+// [variant.visit] //
+/////////////////////
+
+template <typename T>
+struct ConvertTo {
+  template <typename U>
+  T operator()(const U& u) const {
+    return u;
+  }
+};
+
+TEST(VariantTest, VisitSimple) {
+  variant<std::string, const char*> v = "A";
+
+  std::string str = absl::visit(ConvertTo<std::string>{}, v);
+  EXPECT_EQ("A", str);
+
+  v = std::string("B");
+
+  absl::string_view piece = absl::visit(ConvertTo<absl::string_view>{}, v);
+  EXPECT_EQ("B", piece);
+
+  struct StrLen {
+    int operator()(const std::string& s) const { return s.size(); }
+    int operator()(const char* s) const { return strlen(s); }
+  };
+
+  v = "SomeStr";
+  EXPECT_EQ(7, absl::visit(StrLen{}, v));
+  v = std::string("VeryLargeThisTime");
+  EXPECT_EQ(17, absl::visit(StrLen{}, v));
+}
+
+TEST(VariantTest, VisitRValue) {
+  variant<std::string> v = std::string("X");
+  struct Visitor {
+    bool operator()(const std::string&) const { return false; }
+    bool operator()(std::string&&) const { return true; }  // NOLINT
+
+    int operator()(const std::string&, const std::string&) const { return 0; }
+    int operator()(const std::string&, std::string&&) const { return 1; }  // NOLINT
+    int operator()(std::string&&, const std::string&) const { return 2; }  // NOLINT
+    int operator()(std::string&&, std::string&&) const { return 3; }       // NOLINT
+  };
+  EXPECT_FALSE(absl::visit(Visitor{}, v));
+  EXPECT_TRUE(absl::visit(Visitor{}, absl::move(v)));
+
+  // Also test the variadic overload.
+  EXPECT_EQ(0, absl::visit(Visitor{}, v, v));
+  EXPECT_EQ(1, absl::visit(Visitor{}, v, absl::move(v)));
+  EXPECT_EQ(2, absl::visit(Visitor{}, absl::move(v), v));
+  EXPECT_EQ(3, absl::visit(Visitor{}, absl::move(v), absl::move(v)));
+}
+
+TEST(VariantTest, VisitRValueVisitor) {
+  variant<std::string> v = std::string("X");
+  struct Visitor {
+    bool operator()(const std::string&) const& { return false; }
+    bool operator()(const std::string&) && { return true; }
+  };
+  Visitor visitor;
+  EXPECT_FALSE(absl::visit(visitor, v));
+  EXPECT_TRUE(absl::visit(Visitor{}, v));
+}
+
+TEST(VariantTest, VisitResultTypeDifferent) {
+  variant<std::string> v = std::string("X");
+  struct LValue_LValue {};
+  struct RValue_LValue {};
+  struct LValue_RValue {};
+  struct RValue_RValue {};
+  struct Visitor {
+    LValue_LValue operator()(const std::string&) const& { return {}; }
+    RValue_LValue operator()(std::string&&) const& { return {}; }  // NOLINT
+    LValue_RValue operator()(const std::string&) && { return {}; }
+    RValue_RValue operator()(std::string&&) && { return {}; }  // NOLINT
+  } visitor;
+
+  EXPECT_TRUE(
+      (std::is_same<LValue_LValue, decltype(absl::visit(visitor, v))>::value));
+  EXPECT_TRUE(
+      (std::is_same<RValue_LValue,
+                    decltype(absl::visit(visitor, absl::move(v)))>::value));
+  EXPECT_TRUE((
+      std::is_same<LValue_RValue, decltype(absl::visit(Visitor{}, v))>::value));
+  EXPECT_TRUE(
+      (std::is_same<RValue_RValue,
+                    decltype(absl::visit(Visitor{}, absl::move(v)))>::value));
+}
+
+TEST(VariantTest, VisitVariadic) {
+  using A = variant<int, std::string>;
+  using B = variant<std::unique_ptr<int>, absl::string_view>;
+
+  struct Visitor {
+    std::pair<int, int> operator()(int a, std::unique_ptr<int> b) const {
+      return {a, *b};
+    }
+    std::pair<int, int> operator()(absl::string_view a,
+                                   std::unique_ptr<int> b) const {
+      return {static_cast<int>(a.size()), static_cast<int>(*b)};
+    }
+    std::pair<int, int> operator()(int a, absl::string_view b) const {
+      return {a, static_cast<int>(b.size())};
+    }
+    std::pair<int, int> operator()(absl::string_view a,
+                                   absl::string_view b) const {
+      return {static_cast<int>(a.size()), static_cast<int>(b.size())};
+    }
+  };
+
+  EXPECT_THAT(absl::visit(Visitor(), A(1), B(std::unique_ptr<int>(new int(7)))),
+              ::testing::Pair(1, 7));
+  EXPECT_THAT(absl::visit(Visitor(), A(1), B(absl::string_view("ABC"))),
+              ::testing::Pair(1, 3));
+  EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
+                          B(std::unique_ptr<int>(new int(7)))),
+              ::testing::Pair(5, 7));
+  EXPECT_THAT(
+      absl::visit(Visitor(), A(std::string("BBBBB")), B(absl::string_view("ABC"))),
+      ::testing::Pair(5, 3));
+}
+
+TEST(VariantTest, VisitNoArgs) {
+  EXPECT_EQ(5, absl::visit([] { return 5; }));
+}
+
+struct ConstFunctor {
+  int operator()(int a, int b) const { return a - b; }
+};
+
+struct MutableFunctor {
+  int operator()(int a, int b) { return a - b; }
+};
+
+struct Class {
+  int Method(int a, int b) { return a - b; }
+  int ConstMethod(int a, int b) const { return a - b; }
+
+  int member;
+};
+
+TEST(VariantTest, VisitReferenceWrapper) {
+  ConstFunctor cf;
+  MutableFunctor mf;
+  absl::variant<int> three = 3;
+  absl::variant<int> two = 2;
+
+  EXPECT_EQ(1, absl::visit(std::cref(cf), three, two));
+  EXPECT_EQ(1, absl::visit(std::ref(cf), three, two));
+  EXPECT_EQ(1, absl::visit(std::ref(mf), three, two));
+}
+
+// libstdc++ std::variant doesn't support the INVOKE semantics.
+#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+TEST(VariantTest, VisitMemberFunction) {
+  absl::variant<std::unique_ptr<Class>> p(absl::make_unique<Class>());
+  absl::variant<std::unique_ptr<const Class>> cp(
+      absl::make_unique<const Class>());
+  absl::variant<int> three = 3;
+  absl::variant<int> two = 2;
+
+  EXPECT_EQ(1, absl::visit(&Class::Method, p, three, two));
+  EXPECT_EQ(1, absl::visit(&Class::ConstMethod, p, three, two));
+  EXPECT_EQ(1, absl::visit(&Class::ConstMethod, cp, three, two));
+}
+
+TEST(VariantTest, VisitDataMember) {
+  absl::variant<std::unique_ptr<Class>> p(absl::make_unique<Class>(Class{42}));
+  absl::variant<std::unique_ptr<const Class>> cp(
+      absl::make_unique<const Class>(Class{42}));
+  EXPECT_EQ(42, absl::visit(&Class::member, p));
+
+  absl::visit(&Class::member, p) = 5;
+  EXPECT_EQ(5, absl::visit(&Class::member, p));
+
+  EXPECT_EQ(42, absl::visit(&Class::member, cp));
+}
+#endif  // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+
+/////////////////////////
+// [variant.monostate] //
+/////////////////////////
+
+TEST(VariantTest, MonostateBasic) {
+  absl::monostate mono;
+  (void)mono;
+
+  // TODO(mattcalabrese) Expose move triviality metafunctions in absl.
+  EXPECT_TRUE(absl::is_trivially_default_constructible<absl::monostate>::value);
+  EXPECT_TRUE(is_trivially_move_constructible<absl::monostate>::value);
+  EXPECT_TRUE(absl::is_trivially_copy_constructible<absl::monostate>::value);
+  EXPECT_TRUE(is_trivially_move_assignable<absl::monostate>::value);
+  EXPECT_TRUE(absl::is_trivially_copy_assignable<absl::monostate>::value);
+  EXPECT_TRUE(absl::is_trivially_destructible<absl::monostate>::value);
+}
+
+TEST(VariantTest, VariantMonostateDefaultConstruction) {
+  absl::variant<absl::monostate, NonDefaultConstructible> var;
+  EXPECT_EQ(var.index(), 0);
+}
+
+////////////////////////////////
+// [variant.monostate.relops] //
+////////////////////////////////
+
+TEST(VariantTest, MonostateComparisons) {
+  absl::monostate lhs, rhs;
+
+  EXPECT_EQ(lhs, lhs);
+  EXPECT_EQ(lhs, rhs);
+
+  EXPECT_FALSE(lhs != lhs);
+  EXPECT_FALSE(lhs != rhs);
+  EXPECT_FALSE(lhs < lhs);
+  EXPECT_FALSE(lhs < rhs);
+  EXPECT_FALSE(lhs > lhs);
+  EXPECT_FALSE(lhs > rhs);
+
+  EXPECT_LE(lhs, lhs);
+  EXPECT_LE(lhs, rhs);
+  EXPECT_GE(lhs, lhs);
+  EXPECT_GE(lhs, rhs);
+
+  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() ==
+                       std::declval<absl::monostate>()));
+  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() !=
+                       std::declval<absl::monostate>()));
+  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() <
+                       std::declval<absl::monostate>()));
+  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() >
+                       std::declval<absl::monostate>()));
+  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() <=
+                       std::declval<absl::monostate>()));
+  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() >=
+                       std::declval<absl::monostate>()));
+}
+
+///////////////////////
+// [variant.specalg] //
+///////////////////////
+
+TEST(VariantTest, NonmemberSwap) {
+  using std::swap;
+
+  SpecialSwap v1(3);
+  SpecialSwap v2(7);
+
+  variant<SpecialSwap> a = v1, b = v2;
+
+  EXPECT_THAT(a, VariantWith<SpecialSwap>(v1));
+  EXPECT_THAT(b, VariantWith<SpecialSwap>(v2));
+
+  std::swap(a, b);
+  EXPECT_THAT(a, VariantWith<SpecialSwap>(v2));
+  EXPECT_THAT(b, VariantWith<SpecialSwap>(v1));
+#ifndef ABSL_HAVE_STD_VARIANT
+  EXPECT_FALSE(absl::get<SpecialSwap>(a).special_swap);
+#endif
+
+  swap(a, b);
+  EXPECT_THAT(a, VariantWith<SpecialSwap>(v1));
+  EXPECT_THAT(b, VariantWith<SpecialSwap>(v2));
+  EXPECT_TRUE(absl::get<SpecialSwap>(b).special_swap);
+}
+
+//////////////////////////
+// [variant.bad.access] //
+//////////////////////////
+
+TEST(VariantTest, BadAccess) {
+  EXPECT_TRUE(noexcept(absl::bad_variant_access()));
+  absl::bad_variant_access exception_obj;
+  std::exception* base = &exception_obj;
+  (void)base;
+}
+
+////////////////////
+// [variant.hash] //
+////////////////////
+
+TEST(VariantTest, MonostateHash) {
+  absl::monostate mono, other_mono;
+  std::hash<absl::monostate> const hasher{};
+  static_assert(std::is_same<decltype(hasher(mono)), std::size_t>::value, "");
+  EXPECT_EQ(hasher(mono), hasher(other_mono));
+}
+
+TEST(VariantTest, Hash) {
+  static_assert(type_traits_internal::IsHashEnabled<variant<int>>::value, "");
+  static_assert(type_traits_internal::IsHashEnabled<variant<Hashable>>::value,
+                "");
+  static_assert(
+      type_traits_internal::IsHashEnabled<variant<int, Hashable>>::value, "");
+
+#if defined(_MSC_VER) ||                                   \
+    (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 4000 && \
+     _LIBCPP_STD_VER > 11) ||                              \
+    defined(__APPLE__)
+  // For MSVC and libc++ (< 4.0 and c++14), std::hash primary template has a
+  // static_assert to catch any user-defined type T that doesn't provide a hash
+  // specialization. So instantiating std::hash<variant<T>> will result
+  // in a hard error which is not SFINAE friendly.
+#define ABSL_STD_HASH_NOT_SFINAE_FRIENDLY 1
+#endif
+
+#ifndef ABSL_STD_HASH_NOT_SFINAE_FRIENDLY
+  static_assert(
+      !type_traits_internal::IsHashEnabled<variant<NonHashable>>::value, "");
+  static_assert(!type_traits_internal::IsHashEnabled<
+                    variant<Hashable, NonHashable>>::value,
+                "");
+#endif
+
+// MSVC std::hash<std::variant> does not use the index, thus produce the same
+// result on the same value as different alternative.
+#if !(defined(_MSC_VER) && defined(ABSL_HAVE_STD_VARIANT))
+  {
+    // same value as different alternative
+    variant<int, int> v0(in_place_index_t<0>{}, 42);
+    variant<int, int> v1(in_place_index_t<1>{}, 42);
+    std::hash<variant<int, int>> hash;
+    EXPECT_NE(hash(v0), hash(v1));
+  }
+#endif  // !(defined(_MSC_VER) && defined(ABSL_HAVE_STD_VARIANT))
+
+  {
+    std::hash<variant<int>> hash;
+    std::set<size_t> hashcodes;
+    for (int i = 0; i < 100; ++i) {
+      hashcodes.insert(hash(i));
+    }
+    EXPECT_GT(hashcodes.size(), 90);
+
+    // test const-qualified
+    static_assert(
+        type_traits_internal::IsHashEnabled<variant<const int>>::value, "");
+    static_assert(
+        type_traits_internal::IsHashEnabled<variant<const Hashable>>::value,
+        "");
+    std::hash<absl::variant<const int>> c_hash;
+    for (int i = 0; i < 100; ++i) {
+      EXPECT_EQ(hash(i), c_hash(i));
+    }
+  }
+}
+
+////////////////////////////////////////
+// Miscellaneous and deprecated tests //
+////////////////////////////////////////
+
+// Test that a set requiring a basic type conversion works correctly.
+TEST(VariantTest, TestConvertingSet) {
+  typedef variant<double> Variant;
+  Variant v(1.0);
+  const int two = 2;
+  v = two;
+  EXPECT_TRUE(absl::holds_alternative<double>(v));
+  ASSERT_TRUE(nullptr != absl::get_if<double>(&v));
+  EXPECT_DOUBLE_EQ(2, absl::get<double>(v));
+}
+
+// Test that a vector of variants behaves reasonably.
+TEST(VariantTest, Container) {
+  typedef variant<int, float> Variant;
+
+  // Creation of vector should work
+  std::vector<Variant> vec;
+  vec.push_back(Variant(10));
+  vec.push_back(Variant(20.0f));
+
+  // Vector resizing should work if we supply a value for new slots
+  vec.resize(10, Variant(0));
+}
+
+// Test that a variant with a non-copyable type can be constructed and
+// manipulated to some degree.
+TEST(VariantTest, TestVariantWithNonCopyableType) {
+  typedef variant<int, NonCopyable> Variant;
+  const int kValue = 1;
+  Variant v(kValue);
+  ASSERT_TRUE(absl::holds_alternative<int>(v));
+  EXPECT_EQ(kValue, absl::get<int>(v));
+}
+
+// Test that a variant with a non-copyable type can be transformed to
+// the non-copyable type with a call to `emplace` for different numbers
+// of arguments. We do not need to test this for each of T1 ... T8
+// because `emplace` does not overload on T1 ... to T8, so if this
+// works for any one of T1 ... T8, then it works for all of them. We
+// do need to test that it works with varying numbers of parameters
+// though.
+TEST(VariantTest, TestEmplace) {
+  typedef variant<int, NonCopyable> Variant;
+  const int kValue = 1;
+  Variant v(kValue);
+  ASSERT_TRUE(absl::holds_alternative<int>(v));
+  EXPECT_EQ(kValue, absl::get<int>(v));
+
+  // emplace with zero arguments, then back to 'int'
+  v.emplace<NonCopyable>();
+  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
+  EXPECT_EQ(0, absl::get<NonCopyable>(v).value);
+  v = kValue;
+  ASSERT_TRUE(absl::holds_alternative<int>(v));
+
+  // emplace with one argument:
+  v.emplace<NonCopyable>(1);
+  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
+  EXPECT_EQ(1, absl::get<NonCopyable>(v).value);
+  v = kValue;
+  ASSERT_TRUE(absl::holds_alternative<int>(v));
+
+  // emplace with two arguments:
+  v.emplace<NonCopyable>(1, 2);
+  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
+  EXPECT_EQ(3, absl::get<NonCopyable>(v).value);
+  v = kValue;
+  ASSERT_TRUE(absl::holds_alternative<int>(v));
+
+  // emplace with three arguments
+  v.emplace<NonCopyable>(1, 2, 3);
+  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
+  EXPECT_EQ(6, absl::get<NonCopyable>(v).value);
+  v = kValue;
+  ASSERT_TRUE(absl::holds_alternative<int>(v));
+
+  // emplace with four arguments
+  v.emplace<NonCopyable>(1, 2, 3, 4);
+  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
+  EXPECT_EQ(10, absl::get<NonCopyable>(v).value);
+  v = kValue;
+  ASSERT_TRUE(absl::holds_alternative<int>(v));
+}
+
+TEST(VariantTest, TestEmplaceDestroysCurrentValue) {
+  typedef variant<int, IncrementInDtor, NonCopyable> Variant;
+  int counter = 0;
+  Variant v(0);
+  ASSERT_TRUE(absl::holds_alternative<int>(v));
+  v.emplace<IncrementInDtor>(&counter);
+  ASSERT_TRUE(absl::holds_alternative<IncrementInDtor>(v));
+  ASSERT_EQ(0, counter);
+  v.emplace<NonCopyable>();
+  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
+  EXPECT_EQ(1, counter);
+}
+
+TEST(VariantTest, TestMoveSemantics) {
+  typedef variant<std::unique_ptr<int>, std::unique_ptr<std::string>> Variant;
+
+  // Construct a variant by moving from an element value.
+  Variant v(absl::WrapUnique(new int(10)));
+  EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v));
+
+  // Construct a variant by moving from another variant.
+  Variant v2(absl::move(v));
+  ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v2));
+  ASSERT_NE(nullptr, absl::get<std::unique_ptr<int>>(v2));
+  EXPECT_EQ(10, *absl::get<std::unique_ptr<int>>(v2));
+
+  // Moving from a variant object leaves it holding moved-from value of the
+  // same element type.
+  EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v));
+  ASSERT_NE(nullptr, absl::get_if<std::unique_ptr<int>>(&v));
+  EXPECT_EQ(nullptr, absl::get<std::unique_ptr<int>>(v));
+
+  // Assign a variant from an element value by move.
+  v = absl::make_unique<std::string>("foo");
+  ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v));
+  EXPECT_EQ("foo", *absl::get<std::unique_ptr<std::string>>(v));
+
+  // Move-assign a variant.
+  v2 = absl::move(v);
+  ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v2));
+  EXPECT_EQ("foo", *absl::get<std::unique_ptr<std::string>>(v2));
+  EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v));
+}
+
+variant<int, std::string> PassThrough(const variant<int, std::string>& arg) {
+  return arg;
+}
+
+TEST(VariantTest, TestImplicitConversion) {
+  EXPECT_TRUE(absl::holds_alternative<int>(PassThrough(0)));
+
+  // We still need the explicit cast for std::string, because C++ won't apply
+  // two user-defined implicit conversions in a row.
+  EXPECT_TRUE(absl::holds_alternative<std::string>(PassThrough(std::string("foo"))));
+}
+
+struct Convertible2;
+struct Convertible1 {
+  Convertible1() {}
+  Convertible1(const Convertible1&) {}
+  Convertible1& operator=(const Convertible1&) { return *this; }
+
+  // implicit conversion from Convertible2
+  Convertible1(const Convertible2&) {}  // NOLINT(runtime/explicit)
+};
+
+struct Convertible2 {
+  Convertible2() {}
+  Convertible2(const Convertible2&) {}
+  Convertible2& operator=(const Convertible2&) { return *this; }
+
+  // implicit conversion from Convertible1
+  Convertible2(const Convertible1&) {}  // NOLINT(runtime/explicit)
+};
+
+TEST(VariantTest, TestRvalueConversion) {
+  variant<double, std::string> var(
+      ConvertVariantTo<variant<double, std::string>>(variant<std::string, int>(0)));
+  ASSERT_TRUE(absl::holds_alternative<double>(var));
+  EXPECT_EQ(0.0, absl::get<double>(var));
+
+  var = ConvertVariantTo<variant<double, std::string>>(
+      variant<const char*, float>("foo"));
+  ASSERT_TRUE(absl::holds_alternative<std::string>(var));
+  EXPECT_EQ("foo", absl::get<std::string>(var));
+
+  variant<double> singleton(
+      ConvertVariantTo<variant<double>>(variant<int, float>(42)));
+  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
+  EXPECT_EQ(42.0, absl::get<double>(singleton));
+
+  singleton = ConvertVariantTo<variant<double>>(variant<int, float>(3.14f));
+  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
+  EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton)));
+
+  singleton = ConvertVariantTo<variant<double>>(variant<int>(0));
+  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
+  EXPECT_EQ(0.0, absl::get<double>(singleton));
+
+  variant<int32_t, uint32_t> variant2(
+      ConvertVariantTo<variant<int32_t, uint32_t>>(variant<int32_t>(42)));
+  ASSERT_TRUE(absl::holds_alternative<int32_t>(variant2));
+  EXPECT_EQ(42, absl::get<int32_t>(variant2));
+
+  variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
+  ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2));
+  EXPECT_EQ(42, absl::get<uint32_t>(variant2));
+
+  variant<Convertible1, Convertible2> variant3(
+      ConvertVariantTo<variant<Convertible1, Convertible2>>(
+          (variant<Convertible2, Convertible1>(Convertible1()))));
+  ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3));
+
+  variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(
+      variant<Convertible2, Convertible1>(Convertible2()));
+  ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3));
+}
+
+TEST(VariantTest, TestLvalueConversion) {
+  variant<std::string, int> source1 = 0;
+  variant<double, std::string> destination(
+      ConvertVariantTo<variant<double, std::string>>(source1));
+  ASSERT_TRUE(absl::holds_alternative<double>(destination));
+  EXPECT_EQ(0.0, absl::get<double>(destination));
+
+  variant<const char*, float> source2 = "foo";
+  destination = ConvertVariantTo<variant<double, std::string>>(source2);
+  ASSERT_TRUE(absl::holds_alternative<std::string>(destination));
+  EXPECT_EQ("foo", absl::get<std::string>(destination));
+
+  variant<int, float> source3(42);
+  variant<double> singleton(ConvertVariantTo<variant<double>>(source3));
+  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
+  EXPECT_EQ(42.0, absl::get<double>(singleton));
+
+  source3 = 3.14f;
+  singleton = ConvertVariantTo<variant<double>>(source3);
+  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
+  EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton)));
+
+  variant<int> source4(0);
+  singleton = ConvertVariantTo<variant<double>>(source4);
+  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
+  EXPECT_EQ(0.0, absl::get<double>(singleton));
+
+  variant<int32_t> source5(42);
+  variant<int32_t, uint32_t> variant2(
+      ConvertVariantTo<variant<int32_t, uint32_t>>(source5));
+  ASSERT_TRUE(absl::holds_alternative<int32_t>(variant2));
+  EXPECT_EQ(42, absl::get<int32_t>(variant2));
+
+  variant<uint32_t> source6(42);
+  variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6);
+  ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2));
+  EXPECT_EQ(42, absl::get<uint32_t>(variant2));
+
+  variant<Convertible2, Convertible1> source7((Convertible1()));
+  variant<Convertible1, Convertible2> variant3(
+      ConvertVariantTo<variant<Convertible1, Convertible2>>(source7));
+  ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3));
+
+  source7 = Convertible2();
+  variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(source7);
+  ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3));
+}
+
+TEST(VariantTest, TestMoveConversion) {
+  using Variant =
+      variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
+  using OtherVariant = variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+
+  Variant var(
+      ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(0)}));
+  ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const int>>(var));
+  ASSERT_NE(absl::get<std::unique_ptr<const int>>(var), nullptr);
+  EXPECT_EQ(0, *absl::get<std::unique_ptr<const int>>(var));
+
+  var =
+      ConvertVariantTo<Variant>(OtherVariant(absl::make_unique<std::string>("foo")));
+  ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const std::string>>(var));
+  EXPECT_EQ("foo", *absl::get<std::unique_ptr<const std::string>>(var));
+}
+
+TEST(VariantTest, DoesNotMoveFromLvalues) {
+  // We use shared_ptr here because it's both copyable and movable, and
+  // a moved-from shared_ptr is guaranteed to be null, so we can detect
+  // whether moving or copying has occurred.
+  using Variant =
+      variant<std::shared_ptr<const int>, std::shared_ptr<const std::string>>;
+  using OtherVariant = variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
+
+  Variant v1(std::make_shared<const int>(0));
+
+  // Test copy constructor
+  Variant v2(v1);
+  EXPECT_EQ(absl::get<std::shared_ptr<const int>>(v1),
+            absl::get<std::shared_ptr<const int>>(v2));
+
+  // Test copy-assignment operator
+  v1 = std::make_shared<const std::string>("foo");
+  v2 = v1;
+  EXPECT_EQ(absl::get<std::shared_ptr<const std::string>>(v1),
+            absl::get<std::shared_ptr<const std::string>>(v2));
+
+  // Test converting copy constructor
+  OtherVariant other(std::make_shared<int>(0));
+  Variant v3(ConvertVariantTo<Variant>(other));
+  EXPECT_EQ(absl::get<std::shared_ptr<int>>(other),
+            absl::get<std::shared_ptr<const int>>(v3));
+
+  other = std::make_shared<std::string>("foo");
+  v3 = ConvertVariantTo<Variant>(other);
+  EXPECT_EQ(absl::get<std::shared_ptr<std::string>>(other),
+            absl::get<std::shared_ptr<const std::string>>(v3));
+}
+
+TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
+  variant<double, std::string> var(
+      ConvertVariantTo<variant<double, std::string>>(variant<std::string, int>(3)));
+  EXPECT_THAT(absl::get_if<double>(&var), Pointee(3.0));
+
+  var = ConvertVariantTo<variant<double, std::string>>(
+      variant<const char*, float>("foo"));
+  EXPECT_THAT(absl::get_if<std::string>(&var), Pointee(std::string("foo")));
+
+  variant<double> singleton(
+      ConvertVariantTo<variant<double>>(variant<int, float>(42)));
+  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(42.0));
+
+  singleton = ConvertVariantTo<variant<double>>(variant<int, float>(3.14f));
+  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(DoubleEq(3.14f)));
+
+  singleton = ConvertVariantTo<variant<double>>(variant<int>(3));
+  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(3.0));
+
+  variant<int32_t, uint32_t> variant2(
+      ConvertVariantTo<variant<int32_t, uint32_t>>(variant<int32_t>(42)));
+  EXPECT_THAT(absl::get_if<int32_t>(&variant2), Pointee(42));
+
+  variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
+  EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42));
+
+  variant<Convertible1, Convertible2> variant3(
+      ConvertVariantTo<variant<Convertible1, Convertible2>>(
+          (variant<Convertible2, Convertible1>(Convertible1()))));
+  ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3));
+
+  variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(
+      variant<Convertible2, Convertible1>(Convertible2()));
+  ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3));
+}
+
+TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
+  variant<std::string, int> source1 = 3;
+  variant<double, std::string> destination(
+      ConvertVariantTo<variant<double, std::string>>(source1));
+  EXPECT_THAT(absl::get_if<double>(&destination), Pointee(3.0));
+
+  variant<const char*, float> source2 = "foo";
+  destination = ConvertVariantTo<variant<double, std::string>>(source2);
+  EXPECT_THAT(absl::get_if<std::string>(&destination), Pointee(std::string("foo")));
+
+  variant<int, float> source3(42);
+  variant<double> singleton(ConvertVariantTo<variant<double>>(source3));
+  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(42.0));
+
+  source3 = 3.14f;
+  singleton = ConvertVariantTo<variant<double>>(source3);
+  EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton)));
+  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(DoubleEq(3.14f)));
+
+  variant<int> source4(3);
+  singleton = ConvertVariantTo<variant<double>>(source4);
+  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(3.0));
+
+  variant<int32_t> source5(42);
+  variant<int32_t, uint32_t> variant2(
+      ConvertVariantTo<variant<int32_t, uint32_t>>(source5));
+  EXPECT_THAT(absl::get_if<int32_t>(&variant2), Pointee(42));
+
+  variant<uint32_t> source6(42);
+  variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6);
+  EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42));
+
+  variant<Convertible2, Convertible1> source7((Convertible1()));
+  variant<Convertible1, Convertible2> variant3(
+      ConvertVariantTo<variant<Convertible1, Convertible2>>(source7));
+  ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3));
+
+  source7 = Convertible2();
+  variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(source7);
+  ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3));
+}
+
+TEST(VariantTest, TestMoveConversionViaConvertVariantTo) {
+  using Variant =
+      variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
+  using OtherVariant = variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+
+  Variant var(
+      ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(3)}));
+  EXPECT_THAT(absl::get_if<std::unique_ptr<const int>>(&var),
+              Pointee(Pointee(3)));
+
+  var =
+      ConvertVariantTo<Variant>(OtherVariant(absl::make_unique<std::string>("foo")));
+  EXPECT_THAT(absl::get_if<std::unique_ptr<const std::string>>(&var),
+              Pointee(Pointee(std::string("foo"))));
+}
+
+// If all alternatives are trivially copy/move constructible, variant should
+// also be trivially copy/move constructible. This is not required by the
+// standard and we know that libstdc++ variant doesn't have this feature.
+// For more details see the paper:
+// http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0602r0.html
+#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#define ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY 1
+#endif
+
+TEST(VariantTest, TestCopyAndMoveTypeTraits) {
+  EXPECT_TRUE(std::is_copy_constructible<variant<std::string>>::value);
+  EXPECT_TRUE(std::is_copy_assignable<variant<std::string>>::value);
+  EXPECT_TRUE(std::is_move_constructible<variant<std::string>>::value);
+  EXPECT_TRUE(std::is_move_assignable<variant<std::string>>::value);
+  EXPECT_TRUE(std::is_move_constructible<variant<std::unique_ptr<int>>>::value);
+  EXPECT_TRUE(std::is_move_assignable<variant<std::unique_ptr<int>>>::value);
+  EXPECT_FALSE(
+      std::is_copy_constructible<variant<std::unique_ptr<int>>>::value);
+  EXPECT_FALSE(std::is_copy_assignable<variant<std::unique_ptr<int>>>::value);
+
+  EXPECT_FALSE(
+      absl::is_trivially_copy_constructible<variant<std::string>>::value);
+  EXPECT_FALSE(absl::is_trivially_copy_assignable<variant<std::string>>::value);
+#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
+  EXPECT_TRUE(absl::is_trivially_copy_constructible<variant<int>>::value);
+  EXPECT_TRUE(absl::is_trivially_copy_assignable<variant<int>>::value);
+  EXPECT_TRUE(is_trivially_move_constructible<variant<int>>::value);
+  EXPECT_TRUE(is_trivially_move_assignable<variant<int>>::value);
+#endif  // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
+}
+
+TEST(VariantTest, TestVectorOfMoveonlyVariant) {
+  // Verify that variant<MoveonlyType> works correctly as a std::vector element.
+  std::vector<variant<std::unique_ptr<int>, std::string>> vec;
+  vec.push_back(absl::make_unique<int>(42));
+  vec.emplace_back("Hello");
+  vec.reserve(3);
+  auto another_vec = absl::move(vec);
+  // As a sanity check, verify vector contents.
+  ASSERT_EQ(2, another_vec.size());
+  EXPECT_EQ(42, *absl::get<std::unique_ptr<int>>(another_vec[0]));
+  EXPECT_EQ("Hello", absl::get<std::string>(another_vec[1]));
+}
+
+TEST(VariantTest, NestedVariant) {
+#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
+  static_assert(absl::is_trivially_copy_constructible<variant<int>>(), "");
+  static_assert(absl::is_trivially_copy_assignable<variant<int>>(), "");
+  static_assert(is_trivially_move_constructible<variant<int>>(), "");
+  static_assert(is_trivially_move_assignable<variant<int>>(), "");
+
+  static_assert(absl::is_trivially_copy_constructible<variant<variant<int>>>(),
+                "");
+  static_assert(absl::is_trivially_copy_assignable<variant<variant<int>>>(),
+                "");
+  static_assert(is_trivially_move_constructible<variant<variant<int>>>(), "");
+  static_assert(is_trivially_move_assignable<variant<variant<int>>>(), "");
+#endif  // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
+
+  variant<int> x(42);
+  variant<variant<int>> y(x);
+  variant<variant<int>> z(y);
+  EXPECT_TRUE(absl::holds_alternative<variant<int>>(z));
+  EXPECT_EQ(x, absl::get<variant<int>>(z));
+}
+
+struct TriviallyDestructible {
+  TriviallyDestructible(TriviallyDestructible&&) {}
+  TriviallyDestructible(const TriviallyDestructible&) {}
+  TriviallyDestructible& operator=(TriviallyDestructible&&) { return *this; }
+  TriviallyDestructible& operator=(const TriviallyDestructible&) {
+    return *this;
+  }
+};
+
+struct TriviallyMovable {
+  TriviallyMovable(TriviallyMovable&&) = default;
+  TriviallyMovable(TriviallyMovable const&) {}
+  TriviallyMovable& operator=(const TriviallyMovable&) { return *this; }
+};
+
+struct TriviallyCopyable {
+  TriviallyCopyable(const TriviallyCopyable&) = default;
+  TriviallyCopyable& operator=(const TriviallyCopyable&) { return *this; }
+};
+
+struct TriviallyMoveAssignable {
+  TriviallyMoveAssignable(TriviallyMoveAssignable&&) = default;
+  TriviallyMoveAssignable(const TriviallyMoveAssignable&) {}
+  TriviallyMoveAssignable& operator=(TriviallyMoveAssignable&&) = default;
+  TriviallyMoveAssignable& operator=(const TriviallyMoveAssignable&) {
+    return *this;
+  }
+};
+
+struct TriviallyCopyAssignable {};
+
+#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
+TEST(VariantTest, TestTriviality) {
+  {
+    using TrivDestVar = absl::variant<TriviallyDestructible>;
+
+    EXPECT_FALSE(is_trivially_move_constructible<TrivDestVar>::value);
+    EXPECT_FALSE(absl::is_trivially_copy_constructible<TrivDestVar>::value);
+    EXPECT_FALSE(is_trivially_move_assignable<TrivDestVar>::value);
+    EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivDestVar>::value);
+    EXPECT_TRUE(absl::is_trivially_destructible<TrivDestVar>::value);
+  }
+
+  {
+    using TrivMoveVar = absl::variant<TriviallyMovable>;
+
+    EXPECT_TRUE(is_trivially_move_constructible<TrivMoveVar>::value);
+    EXPECT_FALSE(absl::is_trivially_copy_constructible<TrivMoveVar>::value);
+    EXPECT_FALSE(is_trivially_move_assignable<TrivMoveVar>::value);
+    EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivMoveVar>::value);
+    EXPECT_TRUE(absl::is_trivially_destructible<TrivMoveVar>::value);
+  }
+
+  {
+    using TrivCopyVar = absl::variant<TriviallyCopyable>;
+
+    EXPECT_TRUE(is_trivially_move_constructible<TrivCopyVar>::value);
+    EXPECT_TRUE(absl::is_trivially_copy_constructible<TrivCopyVar>::value);
+    EXPECT_FALSE(is_trivially_move_assignable<TrivCopyVar>::value);
+    EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivCopyVar>::value);
+    EXPECT_TRUE(absl::is_trivially_destructible<TrivCopyVar>::value);
+  }
+
+  {
+    using TrivMoveAssignVar = absl::variant<TriviallyMoveAssignable>;
+
+    EXPECT_TRUE(is_trivially_move_constructible<TrivMoveAssignVar>::value);
+    EXPECT_FALSE(
+        absl::is_trivially_copy_constructible<TrivMoveAssignVar>::value);
+    EXPECT_TRUE(is_trivially_move_assignable<TrivMoveAssignVar>::value);
+    EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivMoveAssignVar>::value);
+    EXPECT_TRUE(absl::is_trivially_destructible<TrivMoveAssignVar>::value);
+  }
+
+  {
+    using TrivCopyAssignVar = absl::variant<TriviallyCopyAssignable>;
+
+    EXPECT_TRUE(is_trivially_move_constructible<TrivCopyAssignVar>::value);
+    EXPECT_TRUE(
+        absl::is_trivially_copy_constructible<TrivCopyAssignVar>::value);
+    EXPECT_TRUE(is_trivially_move_assignable<TrivCopyAssignVar>::value);
+    EXPECT_TRUE(absl::is_trivially_copy_assignable<TrivCopyAssignVar>::value);
+    EXPECT_TRUE(absl::is_trivially_destructible<TrivCopyAssignVar>::value);
+  }
+}
+#endif  // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
+
+// To verify that absl::variant correctly use the nontrivial move ctor of its
+// member rather than use the trivial copy constructor.
+TEST(VariantTest, MoveCtorBug) {
+  // To simulate std::tuple in libstdc++.
+  struct TrivialCopyNontrivialMove {
+    TrivialCopyNontrivialMove() = default;
+    TrivialCopyNontrivialMove(const TrivialCopyNontrivialMove&) = default;
+    TrivialCopyNontrivialMove(TrivialCopyNontrivialMove&&) { called = true; }
+    bool called = false;
+  };
+  {
+    using V = absl::variant<TrivialCopyNontrivialMove, int>;
+    V v1(absl::in_place_index_t<0>{});
+    // this should invoke the move ctor, rather than the trivial copy ctor.
+    V v2(std::move(v1));
+    EXPECT_TRUE(absl::get<0>(v2).called);
+  }
+  {
+    // this case failed to compile before our fix due to a GCC bug.
+    using V = absl::variant<int, TrivialCopyNontrivialMove>;
+    V v1(absl::in_place_index_t<1>{});
+    // this should invoke the move ctor, rather than the trivial copy ctor.
+    V v2(std::move(v1));
+    EXPECT_TRUE(absl::get<1>(v2).called);
+  }
+}
+
+}  // namespace
+}  // namespace absl
diff --git a/absl/utility/utility.h b/absl/utility/utility.h
index 1943c4acb577..5b9b84e05d84 100644
--- a/absl/utility/utility.h
+++ b/absl/utility/utility.h
@@ -161,7 +161,7 @@ ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {});
 
 #endif  // ABSL_HAVE_STD_OPTIONAL
 
-#ifdef ABSL_HAVE_STD_ANY
+#if defined(ABSL_HAVE_STD_ANY) || defined(ABSL_HAVE_STD_VARIANT)
 using std::in_place_type_t;
 #else
 
@@ -172,7 +172,11 @@ using std::in_place_type_t;
 // for C++17's `std::in_place_type_t`.
 template <typename T>
 struct in_place_type_t {};
-#endif  // ABSL_HAVE_STD_ANY
+#endif  // ABSL_HAVE_STD_ANY || ABSL_HAVE_STD_VARIANT
+
+#ifdef ABSL_HAVE_STD_VARIANT
+using std::in_place_index_t;
+#else
 
 // in_place_index_t
 //
@@ -181,6 +185,7 @@ struct in_place_type_t {};
 // for C++17's `std::in_place_index_t`.
 template <size_t I>
 struct in_place_index_t {};
+#endif  // ABSL_HAVE_STD_VARIANT
 
 // Constexpr move and forward