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