]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp
Vendor import of libc++ trunk r302418:
[FreeBSD/FreeBSD.git] / test / std / utilities / variant / variant.variant / variant.assign / T.pass.cpp
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 // XFAIL: with_system_cxx_lib=macosx10.12
14 // XFAIL: with_system_cxx_lib=macosx10.11
15 // XFAIL: with_system_cxx_lib=macosx10.10
16 // XFAIL: with_system_cxx_lib=macosx10.9
17 // XFAIL: with_system_cxx_lib=macosx10.7
18 // XFAIL: with_system_cxx_lib=macosx10.8
19
20 // <variant>
21
22 // template <class ...Types> class variant;
23
24 // template <class T>
25 // variant& operator=(T&&) noexcept(see below);
26
27 #include <cassert>
28 #include <string>
29 #include <type_traits>
30 #include <variant>
31
32 #include "test_macros.h"
33 #include "variant_test_helpers.hpp"
34
35 namespace MetaHelpers {
36
37 struct Dummy {
38   Dummy() = default;
39 };
40
41 struct ThrowsCtorT {
42   ThrowsCtorT(int) noexcept(false) {}
43   ThrowsCtorT &operator=(int) noexcept { return *this; }
44 };
45
46 struct ThrowsAssignT {
47   ThrowsAssignT(int) noexcept {}
48   ThrowsAssignT &operator=(int) noexcept(false) { return *this; }
49 };
50
51 struct NoThrowT {
52   NoThrowT(int) noexcept {}
53   NoThrowT &operator=(int) noexcept { return *this; }
54 };
55
56 } // namespace MetaHelpers
57
58 namespace RuntimeHelpers {
59 #ifndef TEST_HAS_NO_EXCEPTIONS
60
61 struct ThrowsCtorT {
62   int value;
63   ThrowsCtorT() : value(0) {}
64   ThrowsCtorT(int) noexcept(false) { throw 42; }
65   ThrowsCtorT &operator=(int v) noexcept {
66     value = v;
67     return *this;
68   }
69 };
70
71 struct ThrowsAssignT {
72   int value;
73   ThrowsAssignT() : value(0) {}
74   ThrowsAssignT(int v) noexcept : value(v) {}
75   ThrowsAssignT &operator=(int) noexcept(false) { throw 42; }
76 };
77
78 struct NoThrowT {
79   int value;
80   NoThrowT() : value(0) {}
81   NoThrowT(int v) noexcept : value(v) {}
82   NoThrowT &operator=(int v) noexcept {
83     value = v;
84     return *this;
85   }
86 };
87
88 #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
89 } // namespace RuntimeHelpers
90
91 void test_T_assignment_noexcept() {
92   using namespace MetaHelpers;
93   {
94     using V = std::variant<Dummy, NoThrowT>;
95     static_assert(std::is_nothrow_assignable<V, int>::value, "");
96   }
97   {
98     using V = std::variant<Dummy, ThrowsCtorT>;
99     static_assert(!std::is_nothrow_assignable<V, int>::value, "");
100   }
101   {
102     using V = std::variant<Dummy, ThrowsAssignT>;
103     static_assert(!std::is_nothrow_assignable<V, int>::value, "");
104   }
105 }
106
107 void test_T_assignment_sfinae() {
108   {
109     using V = std::variant<long, unsigned>;
110     static_assert(!std::is_assignable<V, int>::value, "ambiguous");
111   }
112   {
113     using V = std::variant<std::string, std::string>;
114     static_assert(!std::is_assignable<V, const char *>::value, "ambiguous");
115   }
116   {
117     using V = std::variant<std::string, void *>;
118     static_assert(!std::is_assignable<V, int>::value, "no matching operator=");
119   }
120 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
121   {
122     using V = std::variant<int, int &&>;
123     static_assert(!std::is_assignable<V, int>::value, "ambiguous");
124   }
125   {
126     using V = std::variant<int, const int &>;
127     static_assert(!std::is_assignable<V, int>::value, "ambiguous");
128   }
129 #endif
130 }
131
132 void test_T_assignment_basic() {
133   {
134     std::variant<int> v(43);
135     v = 42;
136     assert(v.index() == 0);
137     assert(std::get<0>(v) == 42);
138   }
139   {
140     std::variant<int, long> v(43l);
141     v = 42;
142     assert(v.index() == 0);
143     assert(std::get<0>(v) == 42);
144     v = 43l;
145     assert(v.index() == 1);
146     assert(std::get<1>(v) == 43);
147   }
148 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
149   {
150     using V = std::variant<int &, int &&, long>;
151     int x = 42;
152     V v(43l);
153     v = x;
154     assert(v.index() == 0);
155     assert(&std::get<0>(v) == &x);
156     v = std::move(x);
157     assert(v.index() == 1);
158     assert(&std::get<1>(v) == &x);
159     // 'long' is selected by FUN(const int &) since 'const int &' cannot bind
160     // to 'int&'.
161     const int &cx = x;
162     v = cx;
163     assert(v.index() == 2);
164     assert(std::get<2>(v) == 42);
165   }
166 #endif
167 }
168
169 void test_T_assignment_performs_construction() {
170   using namespace RuntimeHelpers;
171 #ifndef TEST_HAS_NO_EXCEPTIONS
172   {
173     using V = std::variant<std::string, ThrowsCtorT>;
174     V v(std::in_place_type<std::string>, "hello");
175     try {
176       v = 42;
177     } catch (...) { /* ... */
178     }
179     assert(v.valueless_by_exception());
180   }
181   {
182     using V = std::variant<ThrowsAssignT, std::string>;
183     V v(std::in_place_type<std::string>, "hello");
184     v = 42;
185     assert(v.index() == 0);
186     assert(std::get<0>(v).value == 42);
187   }
188 #endif
189 }
190
191 void test_T_assignment_performs_assignment() {
192   using namespace RuntimeHelpers;
193 #ifndef TEST_HAS_NO_EXCEPTIONS
194   {
195     using V = std::variant<ThrowsCtorT>;
196     V v;
197     v = 42;
198     assert(v.index() == 0);
199     assert(std::get<0>(v).value == 42);
200   }
201   {
202     using V = std::variant<ThrowsCtorT, std::string>;
203     V v;
204     v = 42;
205     assert(v.index() == 0);
206     assert(std::get<0>(v).value == 42);
207   }
208   {
209     using V = std::variant<ThrowsAssignT>;
210     V v(100);
211     try {
212       v = 42;
213       assert(false);
214     } catch (...) { /* ... */
215     }
216     assert(v.index() == 0);
217     assert(std::get<0>(v).value == 100);
218   }
219   {
220     using V = std::variant<std::string, ThrowsAssignT>;
221     V v(100);
222     try {
223       v = 42;
224       assert(false);
225     } catch (...) { /* ... */
226     }
227     assert(v.index() == 1);
228     assert(std::get<1>(v).value == 100);
229   }
230 #endif
231 }
232
233 int main() {
234   test_T_assignment_basic();
235   test_T_assignment_performs_construction();
236   test_T_assignment_performs_assignment();
237   test_T_assignment_noexcept();
238   test_T_assignment_sfinae();
239 }