10373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// -*- C++ -*-
20373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//===----------------------------------------------------------------------===//
30373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//
40373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//                     The LLVM Compiler Infrastructure
50373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//
60373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// This file is dual licensed under the MIT and the University of Illinois Open
70373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// Source Licenses. See LICENSE.TXT for details.
80373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//
90373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//===----------------------------------------------------------------------===//
100373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
110373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// UNSUPPORTED: c++98, c++03, c++11, c++14
120373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
13c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert// XFAIL: with_system_cxx_lib=macosx10.12
14c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert// XFAIL: with_system_cxx_lib=macosx10.11
15c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert// XFAIL: with_system_cxx_lib=macosx10.10
16c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert// XFAIL: with_system_cxx_lib=macosx10.9
17c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert// XFAIL: with_system_cxx_lib=macosx10.7
18c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert// XFAIL: with_system_cxx_lib=macosx10.8
19c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
200373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// <variant>
210373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
220373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// template <class ...Types> class variant;
230373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
240373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// variant(variant&&) noexcept(see below);
250373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
260373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <cassert>
270373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <string>
280373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <type_traits>
290373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <variant>
300373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
310373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include "test_macros.h"
32c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert#include "test_workarounds.h"
330373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
340373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct ThrowsMove {
350373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  ThrowsMove(ThrowsMove &&) noexcept(false) {}
360373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
370373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
380373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct NoCopy {
39cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  NoCopy(const NoCopy &) = delete;
400373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
410373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
420373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct MoveOnly {
430373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  int value;
440373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveOnly(int v) : value(v) {}
45cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  MoveOnly(const MoveOnly &) = delete;
460373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveOnly(MoveOnly &&) = default;
470373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
480373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
490373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct MoveOnlyNT {
500373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  int value;
510373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveOnlyNT(int v) : value(v) {}
52cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  MoveOnlyNT(const MoveOnlyNT &) = delete;
530373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveOnlyNT(MoveOnlyNT &&other) : value(other.value) { other.value = -1; }
540373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
550373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
56c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albertstruct NTMove {
57c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  constexpr NTMove(int v) : value(v) {}
58c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  NTMove(const NTMove &) = delete;
59c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  NTMove(NTMove &&that) : value(that.value) { that.value = -1; }
60c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  int value;
61c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert};
62c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
63c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albertstatic_assert(!std::is_trivially_move_constructible<NTMove>::value, "");
64c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albertstatic_assert(std::is_move_constructible<NTMove>::value, "");
65c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
66c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albertstruct TMove {
67c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  constexpr TMove(int v) : value(v) {}
68c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  TMove(const TMove &) = delete;
69c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  TMove(TMove &&) = default;
70c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  int value;
71c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert};
72c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
73c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albertstatic_assert(std::is_trivially_move_constructible<TMove>::value, "");
74c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
75c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albertstruct TMoveNTCopy {
76c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  constexpr TMoveNTCopy(int v) : value(v) {}
77c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  TMoveNTCopy(const TMoveNTCopy& that) : value(that.value) {}
78c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  TMoveNTCopy(TMoveNTCopy&&) = default;
79c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  int value;
80c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert};
81c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
82c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albertstatic_assert(std::is_trivially_move_constructible<TMoveNTCopy>::value, "");
83c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
840373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#ifndef TEST_HAS_NO_EXCEPTIONS
850373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct MakeEmptyT {
860373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static int alive;
870373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MakeEmptyT() { ++alive; }
88cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  MakeEmptyT(const MakeEmptyT &) {
890373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    ++alive;
900373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    // Don't throw from the copy constructor since variant's assignment
910373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    // operator performs a copy before committing to the assignment.
920373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
930373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MakeEmptyT(MakeEmptyT &&) { throw 42; }
94cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
950373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
960373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  ~MakeEmptyT() { --alive; }
970373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
980373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
990373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierint MakeEmptyT::alive = 0;
1000373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
1010373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliertemplate <class Variant> void makeEmpty(Variant &v) {
1020373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  Variant v2(std::in_place_type<MakeEmptyT>);
1030373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  try {
104c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    v = std::move(v2);
1050373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(false);
1060373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  } catch (...) {
1070373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v.valueless_by_exception());
1080373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1090373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
1100373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#endif // TEST_HAS_NO_EXCEPTIONS
1110373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
1120373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_noexcept() {
1130373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1140373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, long>;
1150373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_nothrow_move_constructible<V>::value, "");
1160373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1170373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1180373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MoveOnly>;
1190373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_nothrow_move_constructible<V>::value, "");
1200373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1210373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1220373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MoveOnlyNT>;
1230373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(!std::is_nothrow_move_constructible<V>::value, "");
1240373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1250373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1260373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, ThrowsMove>;
1270373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(!std::is_nothrow_move_constructible<V>::value, "");
1280373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1290373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
1300373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
1310373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_ctor_sfinae() {
1320373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1330373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, long>;
1340373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_move_constructible<V>::value, "");
1350373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1360373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1370373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MoveOnly>;
1380373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_move_constructible<V>::value, "");
1390373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1400373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1410373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MoveOnlyNT>;
1420373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_move_constructible<V>::value, "");
1430373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1440373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1450373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, NoCopy>;
1460373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(!std::is_move_constructible<V>::value, "");
1470373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
148c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
149c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  // The following tests are for not-yet-standardized behavior (P0602):
150c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  {
151c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    using V = std::variant<int, long>;
152c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(std::is_trivially_move_constructible<V>::value, "");
153c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
154c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  {
155c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    using V = std::variant<int, NTMove>;
156c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(!std::is_trivially_move_constructible<V>::value, "");
157c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(std::is_move_constructible<V>::value, "");
158c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
159c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  {
160c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    using V = std::variant<int, TMove>;
161c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(std::is_trivially_move_constructible<V>::value, "");
162c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
163c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  {
164c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    using V = std::variant<int, TMoveNTCopy>;
165c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(std::is_trivially_move_constructible<V>::value, "");
166c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
1670373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
1680373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
169c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Alberttemplate <typename T>
170c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albertstruct Result { size_t index; T value; };
171c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
1720373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_ctor_basic() {
1730373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1740373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<int> v(std::in_place_index<0>, 42);
1750373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<int> v2 = std::move(v);
1760373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v2.index() == 0);
1770373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<0>(v2) == 42);
1780373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1790373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1800373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<int, long> v(std::in_place_index<1>, 42);
1810373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<int, long> v2 = std::move(v);
1820373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v2.index() == 1);
1830373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<1>(v2) == 42);
1840373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1850373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1860373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<MoveOnly> v(std::in_place_index<0>, 42);
1870373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v.index() == 0);
1880373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<MoveOnly> v2(std::move(v));
1890373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v2.index() == 0);
1900373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<0>(v2).value == 42);
1910373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1920373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1930373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<int, MoveOnly> v(std::in_place_index<1>, 42);
1940373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v.index() == 1);
1950373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<int, MoveOnly> v2(std::move(v));
1960373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v2.index() == 1);
1970373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<1>(v2).value == 42);
1980373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1990373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
2000373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<MoveOnlyNT> v(std::in_place_index<0>, 42);
2010373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v.index() == 0);
2020373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<MoveOnlyNT> v2(std::move(v));
2030373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v2.index() == 0);
2040373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<0>(v).value == -1);
2050373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<0>(v2).value == 42);
2060373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
2070373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
2080373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<int, MoveOnlyNT> v(std::in_place_index<1>, 42);
2090373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v.index() == 1);
2100373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::variant<int, MoveOnlyNT> v2(std::move(v));
2110373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v2.index() == 1);
2120373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<1>(v).value == -1);
2130373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<1>(v2).value == 42);
2140373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
215c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
216c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  // The following tests are for not-yet-standardized behavior (P0602):
217c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  {
218c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    struct {
219c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      constexpr Result<int> operator()() const {
220c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<int> v(std::in_place_index<0>, 42);
221c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<int> v2 = std::move(v);
222c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        return {v2.index(), std::get<0>(std::move(v2))};
223c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      }
224c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    } test;
225c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    constexpr auto result = test();
226c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.index == 0, "");
227c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.value == 42, "");
228c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
229c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  {
230c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    struct {
231c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      constexpr Result<long> operator()() const {
232c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<int, long> v(std::in_place_index<1>, 42);
233c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<int, long> v2 = std::move(v);
234c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        return {v2.index(), std::get<1>(std::move(v2))};
235c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      }
236c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    } test;
237c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    constexpr auto result = test();
238c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.index == 1, "");
239c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.value == 42, "");
240c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
241c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  {
242c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    struct {
243c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      constexpr Result<TMove> operator()() const {
244c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<TMove> v(std::in_place_index<0>, 42);
245c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<TMove> v2(std::move(v));
246c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        return {v2.index(), std::get<0>(std::move(v2))};
247c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      }
248c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    } test;
249c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    constexpr auto result = test();
250c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.index == 0, "");
251c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.value.value == 42, "");
252c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
253c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  {
254c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    struct {
255c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      constexpr Result<TMove> operator()() const {
256c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<int, TMove> v(std::in_place_index<1>, 42);
257c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<int, TMove> v2(std::move(v));
258c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        return {v2.index(), std::get<1>(std::move(v2))};
259c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      }
260c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    } test;
261c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    constexpr auto result = test();
262c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.index == 1, "");
263c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.value.value == 42, "");
264c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
265c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  {
266c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    struct {
267c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      constexpr Result<TMoveNTCopy> operator()() const {
268c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<TMoveNTCopy> v(std::in_place_index<0>, 42);
269c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<TMoveNTCopy> v2(std::move(v));
270c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        return {v2.index(), std::get<0>(std::move(v2))};
271c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      }
272c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    } test;
273c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    constexpr auto result = test();
274c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.index == 0, "");
275c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.value.value == 42, "");
276c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
277c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  {
278c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    struct {
279c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      constexpr Result<TMoveNTCopy> operator()() const {
280c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<int, TMoveNTCopy> v(std::in_place_index<1>, 42);
281c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        std::variant<int, TMoveNTCopy> v2(std::move(v));
282c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        return {v2.index(), std::get<1>(std::move(v2))};
283c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      }
284c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    } test;
285c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    constexpr auto result = test();
286c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.index == 1, "");
287c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    static_assert(result.value.value == 42, "");
288c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
2890373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
2900373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
2910373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_ctor_valueless_by_exception() {
2920373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#ifndef TEST_HAS_NO_EXCEPTIONS
2930373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  using V = std::variant<int, MakeEmptyT>;
2940373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  V v1;
2950373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  makeEmpty(v1);
2960373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  V v(std::move(v1));
2970373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  assert(v.valueless_by_exception());
298c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert#endif // TEST_HAS_NO_EXCEPTIONS
2990373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
3000373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
30108d07da127849a21a223b1400ed394b3a86ff620Eric Fiseliertemplate <size_t Idx>
30208d07da127849a21a223b1400ed394b3a86ff620Eric Fiselierconstexpr bool test_constexpr_ctor_extension_imp(
30308d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier    std::variant<long, void*, const int> const& v)
30408d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier{
30508d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier  auto copy = v;
30608d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier  auto v2 = std::move(copy);
30708d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier  return v2.index() == v.index() &&
30808d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier         v2.index() == Idx &&
30908d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier        std::get<Idx>(v2) == std::get<Idx>(v);
31008d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier}
31108d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier
31208d07da127849a21a223b1400ed394b3a86ff620Eric Fiseliervoid test_constexpr_move_ctor_extension() {
313c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  // NOTE: This test is for not yet standardized behavior. (P0602)
31408d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier  using V = std::variant<long, void*, const int>;
315c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert#ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
316c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  static_assert(std::is_trivially_destructible<V>::value, "");
317c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  static_assert(std::is_trivially_copy_constructible<V>::value, "");
318c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  static_assert(std::is_trivially_move_constructible<V>::value, "");
319c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  static_assert(!std::is_copy_assignable<V>::value, "");
320c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  static_assert(!std::is_move_assignable<V>::value, "");
321c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert#else // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
32208d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier  static_assert(std::is_trivially_copyable<V>::value, "");
323c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert#endif // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
32408d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier  static_assert(std::is_trivially_move_constructible<V>::value, "");
32508d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier  static_assert(test_constexpr_ctor_extension_imp<0>(V(42l)), "");
32608d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier  static_assert(test_constexpr_ctor_extension_imp<1>(V(nullptr)), "");
32708d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier  static_assert(test_constexpr_ctor_extension_imp<2>(V(101)), "");
32808d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier}
32908d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier
3300373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierint main() {
3310373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_ctor_basic();
3320373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_ctor_valueless_by_exception();
3330373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_noexcept();
3340373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_ctor_sfinae();
33508d07da127849a21a223b1400ed394b3a86ff620Eric Fiselier  test_constexpr_move_ctor_extension();
3360373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
337