]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
Vendor import of libc++ trunk r290819:
[FreeBSD/FreeBSD.git] / test / std / utilities / optional / optional.object / optional.object.assign / assign_value.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 // template <class U> optional<T>& operator=(U&& v);
14
15 #include <optional>
16 #include <type_traits>
17 #include <cassert>
18 #include <memory>
19
20 #include "test_macros.h"
21 #include "archetypes.hpp"
22
23 using std::optional;
24
25 struct ThrowAssign {
26   static int dtor_called;
27   ThrowAssign() = default;
28   ThrowAssign(int) { TEST_THROW(42); }
29   ThrowAssign& operator=(int) {
30       TEST_THROW(42);
31   }
32   ~ThrowAssign() { ++dtor_called; }
33 };
34 int ThrowAssign::dtor_called = 0;
35
36 template <class T, class Arg = T, bool Expect = true>
37 void assert_assignable() {
38     static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, "");
39     static_assert(!std::is_assignable<const optional<T>&, Arg>::value, "");
40 }
41
42 struct MismatchType {
43   explicit MismatchType(int) {}
44   explicit MismatchType(char*) {}
45   explicit MismatchType(int*) = delete;
46   MismatchType& operator=(int) { return *this; }
47   MismatchType& operator=(int*) { return *this; }
48   MismatchType& operator=(char*) = delete;
49 };
50
51 struct FromOptionalType {
52   using Opt = std::optional<FromOptionalType>;
53   FromOptionalType() = default;
54   FromOptionalType(FromOptionalType const&) = delete;
55   template <class Dummy = void>
56   constexpr FromOptionalType(Opt&) { Dummy::BARK; }
57   template <class Dummy = void>
58   constexpr FromOptionalType& operator=(Opt&) { Dummy::BARK; return *this; }
59 };
60
61 void test_sfinae() {
62     using I = TestTypes::TestType;
63     using E = ExplicitTestTypes::TestType;
64     assert_assignable<int>();
65     assert_assignable<int, int&>();
66     assert_assignable<int, int const&>();
67     // Implicit test type
68     assert_assignable<I, I const&>();
69     assert_assignable<I, I&&>();
70     assert_assignable<I, int>();
71     assert_assignable<I, void*, false>();
72     // Explicit test type
73     assert_assignable<E, E const&>();
74     assert_assignable<E, E &&>();
75     assert_assignable<E, int>();
76     assert_assignable<E, void*, false>();
77     // Mismatch type
78     assert_assignable<MismatchType, int>();
79     assert_assignable<MismatchType, int*, false>();
80     assert_assignable<MismatchType, char*, false>();
81     // Type constructible from optional
82     assert_assignable<FromOptionalType, std::optional<FromOptionalType>&, false>();
83 }
84
85 void test_with_test_type()
86 {
87     using T = TestTypes::TestType;
88     T::reset();
89     { // to empty
90         optional<T> opt;
91         opt = 3;
92         assert(T::alive == 1);
93         assert(T::constructed == 1);
94         assert(T::value_constructed == 1);
95         assert(T::assigned == 0);
96         assert(T::destroyed == 0);
97         assert(static_cast<bool>(opt) == true);
98         assert(*opt == T(3));
99     }
100     { // to existing
101         optional<T> opt(42);
102         T::reset_constructors();
103         opt = 3;
104         assert(T::alive == 1);
105         assert(T::constructed == 0);
106         assert(T::assigned == 1);
107         assert(T::value_assigned == 1);
108         assert(T::destroyed == 0);
109         assert(static_cast<bool>(opt) == true);
110         assert(*opt == T(3));
111     }
112     { // test default argument
113         optional<T> opt;
114         T::reset_constructors();
115         opt = {1, 2};
116         assert(T::alive == 1);
117         assert(T::constructed == 2);
118         assert(T::value_constructed == 1);
119         assert(T::move_constructed == 1);
120         assert(T::assigned == 0);
121         assert(T::destroyed == 1);
122         assert(static_cast<bool>(opt) == true);
123         assert(*opt == T(1, 2));
124     }
125     { // test default argument
126         optional<T> opt(42);
127         T::reset_constructors();
128         opt = {1, 2};
129         assert(T::alive == 1);
130         assert(T::constructed == 1);
131         assert(T::value_constructed == 1);
132         assert(T::assigned == 1);
133         assert(T::move_assigned == 1);
134         assert(T::destroyed == 1);
135         assert(static_cast<bool>(opt) == true);
136         assert(*opt == T(1, 2));
137     }
138     { // test default argument
139         optional<T> opt;
140         T::reset_constructors();
141         opt = {1};
142         assert(T::alive == 1);
143         assert(T::constructed == 2);
144         assert(T::value_constructed == 1);
145         assert(T::move_constructed == 1);
146         assert(T::assigned == 0);
147         assert(T::destroyed == 1);
148         assert(static_cast<bool>(opt) == true);
149         assert(*opt == T(1));
150     }
151     { // test default argument
152         optional<T> opt(42);
153         T::reset_constructors();
154         opt = {};
155         assert(static_cast<bool>(opt) == false);
156         assert(T::alive == 0);
157         assert(T::constructed == 0);
158         assert(T::assigned == 0);
159         assert(T::destroyed == 1);
160     }
161 }
162
163 template <class T, class Value = int>
164 void test_with_type() {
165     { // to empty
166         optional<T> opt;
167         opt = Value(3);
168         assert(static_cast<bool>(opt) == true);
169         assert(*opt == T(3));
170     }
171     { // to existing
172         optional<T> opt(Value(42));
173         opt = Value(3);
174         assert(static_cast<bool>(opt) == true);
175         assert(*opt == T(3));
176     }
177     { // test const
178         optional<T> opt(Value(42));
179         const T t(Value(3));
180         opt = t;
181         assert(static_cast<bool>(opt) == true);
182         assert(*opt == T(3));
183     }
184     { // test default argument
185         optional<T> opt;
186         opt = {Value(1)};
187         assert(static_cast<bool>(opt) == true);
188         assert(*opt == T(1));
189     }
190     { // test default argument
191         optional<T> opt(Value(42));
192         opt = {};
193         assert(static_cast<bool>(opt) == false);
194     }
195 }
196
197 template <class T>
198 void test_with_type_multi() {
199     test_with_type<T>();
200     { // test default argument
201         optional<T> opt;
202         opt = {1, 2};
203         assert(static_cast<bool>(opt) == true);
204         assert(*opt == T(1, 2));
205     }
206     { // test default argument
207         optional<T> opt(42);
208         opt = {1, 2};
209         assert(static_cast<bool>(opt) == true);
210         assert(*opt == T(1, 2));
211     }
212 }
213
214 void test_throws()
215 {
216 #ifndef TEST_HAS_NO_EXCEPTIONS
217     using T = ThrowAssign;
218     {
219         using T = ThrowAssign;
220         optional<T> opt;
221         try {
222             opt = 42;
223             assert(false);
224         } catch (int) {}
225         assert(static_cast<bool>(opt) == false);
226     }
227     assert(T::dtor_called == 0);
228     {
229         T::dtor_called = 0;
230         optional<T> opt(std::in_place);
231         try {
232             opt = 42;
233             assert(false);
234         } catch (int) {}
235         assert(static_cast<bool>(opt) == true);
236         assert(T::dtor_called == 0);
237     }
238     assert(T::dtor_called == 1);
239 #endif
240 }
241
242 enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 };
243
244 using Fn = void(*)();
245
246 int main()
247 {
248     test_sfinae();
249     // Test with instrumented type
250     test_with_test_type();
251     // Test with various scalar types
252     test_with_type<int>();
253     test_with_type<MyEnum, MyEnum>();
254     test_with_type<int, MyEnum>();
255     test_with_type<Fn, Fn>();
256     // Test types with multi argument constructors
257     test_with_type_multi<ConstexprTestTypes::TestType>();
258     test_with_type_multi<TrivialTestTypes::TestType>();
259     // Test move only types
260     {
261         optional<std::unique_ptr<int>> opt;
262         opt = std::unique_ptr<int>(new int(3));
263         assert(static_cast<bool>(opt) == true);
264         assert(**opt == 3);
265     }
266     {
267         optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2)));
268         opt = std::unique_ptr<int>(new int(3));
269         assert(static_cast<bool>(opt) == true);
270         assert(**opt == 3);
271     }
272     test_throws();
273 }