about summary refs log blame commit diff
path: root/absl/types/variant_test.cc
blob: 9df702dff6c1844d1d47703c2d60804665f9eb27 (plain) (tree)
1
2
3
4
5
6
7
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312





                                                                   
                                                   














































                                                                           
                                                                                

































































                                                                              
                                                   

                                






































































































































                                                                             
                                                 
















































































































































                                                                                
                                                        















































































                                                                                

                                                                          

































                                                                                

                                                                          






































                                                                        



                                                        
                                                             


                                               







































































































































































































































































                                                                                   

                                                                          



































                                                                          

                                                                          




















































































































































































































































































































































































































































                                                                                

                                                























































                                                                              

                                                                           











































































































                                                                              

                                                                           



















































                                                                             

                                                                           









































































































































































































                                                                              






                                                                               










































































                                                                                


                                                             







































































































































































                                                                                


                                                                                
                    
 

                                                                               
                    


                                                                               






















                                                                             

                                                                              
                  
                                                                              



















































































































































                                                                              

                                                                             






















                                                                   

                                                     


























































































                                                                                 

                                                                  






                                                                          

                                                           









                                                                                

                                                                  



























                                                               

                                                     








































                                                                                 

                                                      



































                                                                              

                                                                  





                                                                          

                                                           














                                                                            
                                                                     
                                                                       
                                                                     
                                                                                
                                                                              

                                                                        
                                                                               


































































































































































                                                                                
// 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
//
//      https://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((void)(__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 {
  operator T() const {  // NOLINT(runtime/explicit)
    throw ConversionException();
  }
};

// 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_SUITE(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
    : absl::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
// See comment in absl/base/config.h
#if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
TEST(VariantTest, DISABLED_TestDtorValuelessByException)
#else
// Test destruction when in the valueless_by_exception state.
TEST(VariantTest, TestDtorValuelessByException)
#endif
{
  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::IsHashable<variant<int>>::value, "");
  static_assert(type_traits_internal::IsHashable<variant<Hashable>>::value, "");
  static_assert(type_traits_internal::IsHashable<variant<int, Hashable>>::value,
                "");

#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
  static_assert(!type_traits_internal::IsHashable<variant<NonHashable>>::value,
                "");
  static_assert(
      !type_traits_internal::IsHashable<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::IsHashable<variant<const int>>::value,
                  "");
    static_assert(
        type_traits_internal::IsHashable<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(absl::is_copy_assignable<variant<std::string>>::value);
  EXPECT_TRUE(std::is_move_constructible<variant<std::string>>::value);
  EXPECT_TRUE(absl::is_move_assignable<variant<std::string>>::value);
  EXPECT_TRUE(std::is_move_constructible<variant<std::unique_ptr<int>>>::value);
  EXPECT_TRUE(absl::is_move_assignable<variant<std::unique_ptr<int>>>::value);
  EXPECT_FALSE(
      std::is_copy_constructible<variant<std::unique_ptr<int>>>::value);
  EXPECT_FALSE(absl::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