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
130373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// <variant>
140373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
150373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// template <class ...Types> class variant;
160373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
170373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// variant& operator=(variant&&) noexcept(see below);
180373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
190373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <cassert>
200373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <string>
210373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <type_traits>
220373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <utility>
230373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <variant>
240373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
250373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include "test_macros.h"
260373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include "variant_test_helpers.hpp"
270373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
280373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct NoCopy {
29cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  NoCopy(const NoCopy &) = delete;
30cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  NoCopy &operator=(const NoCopy &) = default;
310373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
320373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
330373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct CopyOnly {
34cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  CopyOnly(const CopyOnly &) = default;
350373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  CopyOnly(CopyOnly &&) = delete;
36cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  CopyOnly &operator=(const CopyOnly &) = default;
370373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  CopyOnly &operator=(CopyOnly &&) = delete;
380373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
390373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
400373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct MoveOnly {
41cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  MoveOnly(const MoveOnly &) = delete;
420373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveOnly(MoveOnly &&) = default;
43cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  MoveOnly &operator=(const MoveOnly &) = delete;
440373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveOnly &operator=(MoveOnly &&) = default;
450373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
460373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
470373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct MoveOnlyNT {
48cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  MoveOnlyNT(const MoveOnlyNT &) = delete;
490373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveOnlyNT(MoveOnlyNT &&) {}
50cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  MoveOnlyNT &operator=(const MoveOnlyNT &) = delete;
510373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveOnlyNT &operator=(MoveOnlyNT &&) = default;
520373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
530373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
540373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct MoveOnlyOddNothrow {
550373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveOnlyOddNothrow(MoveOnlyOddNothrow &&) noexcept(false) {}
56cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  MoveOnlyOddNothrow(const MoveOnlyOddNothrow &) = delete;
570373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveOnlyOddNothrow &operator=(MoveOnlyOddNothrow &&) noexcept = default;
58cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  MoveOnlyOddNothrow &operator=(const MoveOnlyOddNothrow &) = delete;
590373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
600373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
610373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct MoveAssignOnly {
620373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveAssignOnly(MoveAssignOnly &&) = delete;
630373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveAssignOnly &operator=(MoveAssignOnly &&) = default;
640373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
650373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
660373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct MoveAssign {
670373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static int move_construct;
680373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static int move_assign;
690373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static void reset() { move_construct = move_assign = 0; }
700373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveAssign(int v) : value(v) {}
710373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveAssign(MoveAssign &&o) : value(o.value) {
720373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    ++move_construct;
730373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    o.value = -1;
740373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
750373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  MoveAssign &operator=(MoveAssign &&o) {
760373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    value = o.value;
770373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    ++move_assign;
780373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    o.value = -1;
790373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    return *this;
800373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
810373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  int value;
820373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
830373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
840373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierint MoveAssign::move_construct = 0;
850373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierint MoveAssign::move_assign = 0;
860373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
870373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_assignment_noexcept() {
880373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
890373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int>;
900373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_nothrow_move_assignable<V>::value, "");
910373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
920373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
930373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<MoveOnly>;
940373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_nothrow_move_assignable<V>::value, "");
950373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
960373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
970373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, long>;
980373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_nothrow_move_assignable<V>::value, "");
990373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1000373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1010373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MoveOnly>;
1020373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_nothrow_move_assignable<V>::value, "");
1030373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1040373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1050373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<MoveOnlyNT>;
1060373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(!std::is_nothrow_move_assignable<V>::value, "");
1070373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1080373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1090373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<MoveOnlyOddNothrow>;
1100373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(!std::is_nothrow_move_assignable<V>::value, "");
1110373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1120373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
1130373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
1140373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_assignment_sfinae() {
1150373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1160373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, long>;
1170373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_move_assignable<V>::value, "");
1180373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1190373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1200373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    // variant only provides move assignment when both the move constructor
1210373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    // and move assignment operator are well formed.
1220373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, CopyOnly>;
1230373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(!std::is_move_assignable<V>::value, "");
1240373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1250373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1260373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, NoCopy>;
1270373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(!std::is_move_assignable<V>::value, "");
1280373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1290373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1300373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MoveOnly>;
1310373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_move_assignable<V>::value, "");
1320373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1330373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1340373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MoveOnlyNT>;
1350373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(std::is_move_assignable<V>::value, "");
1360373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1370373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1380373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    // variant only provides move assignment when the types also provide
1390373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    // a move constructor.
1400373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MoveAssignOnly>;
1410373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    static_assert(!std::is_move_assignable<V>::value, "");
1420373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1430373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
1440373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
1450373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_assignment_empty_empty() {
1460373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#ifndef TEST_HAS_NO_EXCEPTIONS
1470373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  using MET = MakeEmptyT;
1480373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1490373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, long, MET>;
1500373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(std::in_place_index<0>);
1510373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    makeEmpty(v1);
1520373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(std::in_place_index<0>);
1530373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    makeEmpty(v2);
1540373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
1550373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
1560373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.valueless_by_exception());
1570373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == std::variant_npos);
1580373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1590373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#endif
1600373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
1610373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
1620373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_assignment_non_empty_empty() {
1630373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#ifndef TEST_HAS_NO_EXCEPTIONS
1640373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  using MET = MakeEmptyT;
1650373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1660373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MET>;
1670373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(std::in_place_index<0>, 42);
1680373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(std::in_place_index<0>);
1690373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    makeEmpty(v2);
1700373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
1710373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
1720373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.valueless_by_exception());
1730373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == std::variant_npos);
1740373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1750373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1760373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MET, std::string>;
1770373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(std::in_place_index<2>, "hello");
1780373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(std::in_place_index<0>);
1790373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    makeEmpty(v2);
1800373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
1810373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
1820373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.valueless_by_exception());
1830373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == std::variant_npos);
1840373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
1850373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#endif
1860373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
1870373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
1880373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_assignment_empty_non_empty() {
1890373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#ifndef TEST_HAS_NO_EXCEPTIONS
1900373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  using MET = MakeEmptyT;
1910373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
1920373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MET>;
1930373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(std::in_place_index<0>);
1940373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    makeEmpty(v1);
1950373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(std::in_place_index<0>, 42);
1960373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
1970373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
1980373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == 0);
1990373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<0>(v1) == 42);
2000373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
2010373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
2020373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MET, std::string>;
2030373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(std::in_place_index<0>);
2040373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    makeEmpty(v1);
2050373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(std::in_place_type<std::string>, "hello");
2060373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
2070373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
2080373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == 2);
2090373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<2>(v1) == "hello");
2100373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
2110373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#endif
2120373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
2130373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
2140373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_assignment_same_index() {
2150373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
2160373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int>;
2170373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(43);
2180373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(42);
2190373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
2200373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
2210373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == 0);
2220373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<0>(v1) == 42);
2230373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
2240373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
2250373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, long, unsigned>;
2260373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(43l);
2270373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(42l);
2280373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
2290373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
2300373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == 1);
2310373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<1>(v1) == 42);
2320373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
2330373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
2340373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MoveAssign, unsigned>;
2350373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(std::in_place_type<MoveAssign>, 43);
2360373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(std::in_place_type<MoveAssign>, 42);
2370373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    MoveAssign::reset();
2380373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
2390373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
2400373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == 1);
2410373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<1>(v1).value == 42);
2420373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(MoveAssign::move_construct == 0);
2430373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(MoveAssign::move_assign == 1);
2440373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
2450373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#ifndef TEST_HAS_NO_EXCEPTIONS
2460373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  using MET = MakeEmptyT;
2470373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
2480373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MET, std::string>;
2490373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(std::in_place_type<MET>);
2500373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    MET &mref = std::get<1>(v1);
2510373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(std::in_place_type<MET>);
2520373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    try {
2530373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier      v1 = std::move(v2);
2540373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier      assert(false);
2550373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    } catch (...) {
2560373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    }
2570373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == 1);
2580373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&std::get<1>(v1) == &mref);
2590373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
2600373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#endif
2610373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
2620373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
2630373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_move_assignment_different_index() {
2640373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
2650373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, long, unsigned>;
2660373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(43);
2670373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(42l);
2680373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
2690373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
2700373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == 1);
2710373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<1>(v1) == 42);
2720373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
2730373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
2740373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MoveAssign, unsigned>;
2750373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(std::in_place_type<unsigned>, 43);
2760373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(std::in_place_type<MoveAssign>, 42);
2770373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    MoveAssign::reset();
2780373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
2790373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
2800373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == 1);
2810373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<1>(v1).value == 42);
2820373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(MoveAssign::move_construct == 1);
2830373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(MoveAssign::move_assign == 0);
2840373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
2850373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#ifndef TEST_HAS_NO_EXCEPTIONS
2860373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  using MET = MakeEmptyT;
2870373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
2880373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MET, std::string>;
2890373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(std::in_place_type<int>);
2900373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(std::in_place_type<MET>);
2910373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    try {
2920373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier      v1 = std::move(v2);
2930373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier      assert(false);
2940373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    } catch (...) {
2950373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    }
2960373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.valueless_by_exception());
2970373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == std::variant_npos);
2980373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
2990373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  {
3000373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    using V = std::variant<int, MET, std::string>;
3010373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v1(std::in_place_type<MET>);
3020373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V v2(std::in_place_type<std::string>, "hello");
3030373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    V &vref = (v1 = std::move(v2));
3040373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(&vref == &v1);
3050373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(v1.index() == 2);
3060373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    assert(std::get<2>(v1) == "hello");
3070373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  }
3080373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#endif
3090373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
3100373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
3110373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierint main() {
3120373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_assignment_empty_empty();
3130373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_assignment_non_empty_empty();
3140373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_assignment_empty_non_empty();
3150373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_assignment_same_index();
3160373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_assignment_different_index();
3170373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_assignment_sfinae();
3180373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_move_assignment_noexcept();
3190373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
320