1cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier// -*- C++ -*-
2cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier//===----------------------------------------------------------------------===//
3cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier//
4cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier//                     The LLVM Compiler Infrastructure
5cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier//
6cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier// This file is dual licensed under the MIT and the University of Illinois Open
7cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier// Source Licenses. See LICENSE.TXT for details.
8cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier//
9cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier//===----------------------------------------------------------------------===//
10cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
11cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier// UNSUPPORTED: c++98, c++03, c++11, c++14
12cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
13cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier// <variant>
14cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
15cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier// template <class ...Types> class variant;
16cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
17cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier// variant(variant&&) noexcept(see below);
18cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
19cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier#include <type_traits>
20cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier#include <variant>
21cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
22cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier#include "test_macros.h"
23cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
24cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselierstruct NTMove {
25cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  constexpr NTMove(int v) : value(v) {}
26cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  NTMove(const NTMove &) = delete;
27cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  NTMove(NTMove &&that) : value(that.value) { that.value = -1; }
28cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  int value;
29cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier};
30cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
31cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselierstatic_assert(!std::is_trivially_move_constructible<NTMove>::value, "");
32cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselierstatic_assert(std::is_move_constructible<NTMove>::value, "");
33cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
34cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselierstruct TMove {
35cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  constexpr TMove(int v) : value(v) {}
36cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  TMove(const TMove &) = delete;
37cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  TMove(TMove &&) = default;
38cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  int value;
39cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier};
40cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
41cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselierstatic_assert(std::is_trivially_move_constructible<TMove>::value, "");
42cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
43cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselierstruct TMoveNTCopy {
44cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  constexpr TMoveNTCopy(int v) : value(v) {}
45cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  TMoveNTCopy(const TMoveNTCopy& that) : value(that.value) {}
46cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  TMoveNTCopy(TMoveNTCopy&&) = default;
47cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  int value;
48cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier};
49cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
50cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselierstatic_assert(std::is_trivially_move_constructible<TMoveNTCopy>::value, "");
51cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
52cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiseliervoid test_move_ctor_sfinae() {
53cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  {
54cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    using V = std::variant<int, long>;
55cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    static_assert(std::is_trivially_move_constructible<V>::value, "");
56cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  }
57cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  {
58cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    using V = std::variant<int, NTMove>;
59cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    static_assert(!std::is_trivially_move_constructible<V>::value, "");
60cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    static_assert(std::is_move_constructible<V>::value, "");
61cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  }
62cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  {
63cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    using V = std::variant<int, TMove>;
64cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    static_assert(std::is_trivially_move_constructible<V>::value, "");
65cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  }
66cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  {
67cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    using V = std::variant<int, TMoveNTCopy>;
68cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    static_assert(std::is_trivially_move_constructible<V>::value, "");
69cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  }
70cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier}
71cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
72cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiseliertemplate <typename T>
73cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselierstruct Result { size_t index; T value; };
74cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
75cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiseliervoid test_move_ctor_basic() {
76cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  {
77cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    struct {
78cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      constexpr Result<int> operator()() const {
79cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<int> v(std::in_place_index<0>, 42);
80cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<int> v2 = std::move(v);
81cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        return {v2.index(), std::get<0>(std::move(v2))};
82cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      }
83cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    } test;
84cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    constexpr auto result = test();
859c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.index == 0, "");
869c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.value == 42, "");
87cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  }
88cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  {
89cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    struct {
90cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      constexpr Result<long> operator()() const {
91cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<int, long> v(std::in_place_index<1>, 42);
92cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<int, long> v2 = std::move(v);
93cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        return {v2.index(), std::get<1>(std::move(v2))};
94cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      }
95cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    } test;
96cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    constexpr auto result = test();
979c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.index == 1, "");
989c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.value == 42, "");
99cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  }
100cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  {
101cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    struct {
102cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      constexpr Result<TMove> operator()() const {
103cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<TMove> v(std::in_place_index<0>, 42);
104cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<TMove> v2(std::move(v));
105cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        return {v2.index(), std::get<0>(std::move(v2))};
106cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      }
107cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    } test;
108cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    constexpr auto result = test();
1099c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.index == 0, "");
1109c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.value.value == 42, "");
111cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  }
112cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  {
113cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    struct {
114cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      constexpr Result<TMove> operator()() const {
115cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<int, TMove> v(std::in_place_index<1>, 42);
116cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<int, TMove> v2(std::move(v));
117cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        return {v2.index(), std::get<1>(std::move(v2))};
118cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      }
119cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    } test;
120cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    constexpr auto result = test();
1219c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.index == 1, "");
1229c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.value.value == 42, "");
123cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  }
124cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  {
125cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    struct {
126cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      constexpr Result<TMoveNTCopy> operator()() const {
127cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<TMoveNTCopy> v(std::in_place_index<0>, 42);
128cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<TMoveNTCopy> v2(std::move(v));
129cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        return {v2.index(), std::get<0>(std::move(v2))};
130cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      }
131cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    } test;
132cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    constexpr auto result = test();
1339c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.index == 0, "");
1349c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.value.value == 42, "");
135cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  }
136cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  {
137cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    struct {
138cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      constexpr Result<TMoveNTCopy> operator()() const {
139cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<int, TMoveNTCopy> v(std::in_place_index<1>, 42);
140cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        std::variant<int, TMoveNTCopy> v2(std::move(v));
141cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier        return {v2.index(), std::get<1>(std::move(v2))};
142cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier      }
143cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    } test;
144cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier    constexpr auto result = test();
1459c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.index == 1, "");
1469c6b70a0afc86ebdcff070ca5020497df5d62889Eric Fiselier    static_assert(result.value.value == 42, "");
147cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  }
148cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier}
149cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier
150cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselierint main() {
151cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  test_move_ctor_basic();
152cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier  test_move_ctor_sfinae();
153cab2af84188b519bf9ae8ac75641ee06ada49a4eEric Fiselier}
154