]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
Vendor import of libc++ trunk r290819:
[FreeBSD/FreeBSD.git] / test / std / utilities / optional / optional.object / optional.object.assign / optional_U.pass.cpp
1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // UNSUPPORTED: c++98, c++03, c++11, c++14
11 // <optional>
12
13 // From LWG2451:
14 // template <class U>
15 // optional<T>& operator=(optional<U>&& rhs);
16
17 #include <optional>
18 #include <type_traits>
19 #include <memory>
20 #include <cassert>
21
22 #include "test_macros.h"
23 #include "archetypes.hpp"
24
25 using std::optional;
26
27 struct X
28 {
29     static bool throw_now;
30
31     X() = default;
32     X(int &&)
33     {
34         if (throw_now)
35             TEST_THROW(6);
36     }
37 };
38
39 bool X::throw_now = false;
40
41 struct Y1
42 {
43     Y1() = default;
44     Y1(const int&) {}
45     Y1& operator=(const Y1&) = delete;
46 };
47
48 struct Y2
49 {
50     Y2() = default;
51     Y2(const int&) = delete;
52     Y2& operator=(const int&) { return *this; }
53 };
54
55 class B {};
56 class D : public B {};
57
58
59 template <class T>
60 struct AssignableFrom {
61   static int type_constructed;
62   static int type_assigned;
63 static int int_constructed;
64   static int int_assigned;
65
66   static void reset() {
67       type_constructed = int_constructed = 0;
68       type_assigned = int_assigned = 0;
69   }
70
71   AssignableFrom() = default;
72
73   explicit AssignableFrom(T) { ++type_constructed; }
74   AssignableFrom& operator=(T) { ++type_assigned; return *this; }
75
76   AssignableFrom(int) { ++int_constructed; }
77   AssignableFrom& operator=(int) { ++int_assigned; return *this; }
78 private:
79   AssignableFrom(AssignableFrom const&) = delete;
80   AssignableFrom& operator=(AssignableFrom const&) = delete;
81 };
82
83 template <class T> int AssignableFrom<T>::type_constructed = 0;
84 template <class T> int AssignableFrom<T>::type_assigned = 0;
85 template <class T> int AssignableFrom<T>::int_constructed = 0;
86 template <class T> int AssignableFrom<T>::int_assigned = 0;
87
88 void test_with_test_type() {
89     using T = TestTypes::TestType;
90     T::reset();
91     { // non-empty to empty
92         T::reset_constructors();
93         optional<T> opt;
94         optional<int> other(42);
95         opt = std::move(other);
96         assert(T::alive == 1);
97         assert(T::constructed == 1);
98         assert(T::value_constructed == 1);
99         assert(T::assigned == 0);
100         assert(T::destroyed == 0);
101         assert(static_cast<bool>(other) == true);
102         assert(*other == 42);
103         assert(static_cast<bool>(opt) == true);
104         assert(*opt == T(42));
105     }
106     assert(T::alive == 0);
107     { // non-empty to non-empty
108         optional<T> opt(101);
109         optional<int> other(42);
110         T::reset_constructors();
111         opt = std::move(other);
112         assert(T::alive == 1);
113         assert(T::constructed == 0);
114         assert(T::assigned == 1);
115         assert(T::value_assigned == 1);
116         assert(T::destroyed == 0);
117         assert(static_cast<bool>(other) == true);
118         assert(*other == 42);
119         assert(static_cast<bool>(opt) == true);
120         assert(*opt == T(42));
121     }
122     assert(T::alive == 0);
123     { // empty to non-empty
124         optional<T> opt(101);
125         optional<int> other;
126         T::reset_constructors();
127         opt = std::move(other);
128         assert(T::alive == 0);
129         assert(T::constructed == 0);
130         assert(T::assigned == 0);
131         assert(T::destroyed == 1);
132         assert(static_cast<bool>(other) == false);
133         assert(static_cast<bool>(opt) == false);
134     }
135     assert(T::alive == 0);
136     { // empty to empty
137         optional<T> opt;
138         optional<int> other;
139         T::reset_constructors();
140         opt = std::move(other);
141         assert(T::alive == 0);
142         assert(T::constructed == 0);
143         assert(T::assigned == 0);
144         assert(T::destroyed == 0);
145         assert(static_cast<bool>(other) == false);
146         assert(static_cast<bool>(opt) == false);
147     }
148     assert(T::alive == 0);
149 }
150
151
152 void test_ambigious_assign() {
153     using OptInt = std::optional<int>;
154     {
155         using T = AssignableFrom<OptInt&&>;
156         T::reset();
157         {
158             OptInt a(42);
159             std::optional<T> t;
160             t = std::move(a);
161             assert(T::type_constructed == 1);
162             assert(T::type_assigned == 0);
163             assert(T::int_constructed == 0);
164             assert(T::int_assigned == 0);
165         }
166         {
167             using Opt = std::optional<T>;
168             static_assert(!std::is_assignable<Opt&, const OptInt&&>::value, "");
169             static_assert(!std::is_assignable<Opt&, const OptInt&>::value, "");
170             static_assert(!std::is_assignable<Opt&, OptInt&>::value, "");
171         }
172     }
173     {
174         using T = AssignableFrom<OptInt const&&>;
175         T::reset();
176         {
177             const OptInt a(42);
178             std::optional<T> t;
179             t = std::move(a);
180             assert(T::type_constructed == 1);
181             assert(T::type_assigned == 0);
182             assert(T::int_constructed == 0);
183             assert(T::int_assigned == 0);
184         }
185         T::reset();
186         {
187             OptInt a(42);
188             std::optional<T> t;
189             t = std::move(a);
190             assert(T::type_constructed == 1);
191             assert(T::type_assigned == 0);
192             assert(T::int_constructed == 0);
193             assert(T::int_assigned == 0);
194         }
195         {
196             using Opt = std::optional<T>;
197             static_assert(std::is_assignable<Opt&, OptInt&&>::value, "");
198             static_assert(!std::is_assignable<Opt&, const OptInt&>::value, "");
199             static_assert(!std::is_assignable<Opt&, OptInt&>::value, "");
200         }
201     }
202 }
203
204
205 int main()
206 {
207     test_with_test_type();
208     test_ambigious_assign();
209     {
210         optional<int> opt;
211         optional<short> opt2;
212         opt = std::move(opt2);
213         assert(static_cast<bool>(opt2) == false);
214         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
215     }
216     {
217         optional<int> opt;
218         optional<short> opt2(short{2});
219         opt = std::move(opt2);
220         assert(static_cast<bool>(opt2) == true);
221         assert(*opt2 == 2);
222         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
223         assert(*opt == *opt2);
224     }
225     {
226         optional<int> opt(3);
227         optional<short> opt2;
228         opt = std::move(opt2);
229         assert(static_cast<bool>(opt2) == false);
230         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
231     }
232     {
233         optional<int> opt(3);
234         optional<short> opt2(short{2});
235         opt = std::move(opt2);
236         assert(static_cast<bool>(opt2) == true);
237         assert(*opt2 == 2);
238         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
239         assert(*opt == *opt2);
240     }
241     {
242         optional<std::unique_ptr<B>> opt;
243         optional<std::unique_ptr<D>> other(new D());
244         opt = std::move(other);
245         assert(static_cast<bool>(opt) == true);
246         assert(static_cast<bool>(other) == true);
247         assert(opt->get() != nullptr);
248         assert(other->get() == nullptr);
249     }
250 #ifndef TEST_HAS_NO_EXCEPTIONS
251     {
252         optional<X> opt;
253         optional<int> opt2(42);
254         assert(static_cast<bool>(opt2) == true);
255         try
256         {
257             X::throw_now = true;
258             opt = std::move(opt2);
259             assert(false);
260         }
261         catch (int i)
262         {
263             assert(i == 6);
264             assert(static_cast<bool>(opt) == false);
265         }
266     }
267 #endif
268 }