• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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=(const optional<U>& rhs);
16 
17 #include <optional>
18 #include <type_traits>
19 #include <cassert>
20 
21 #include "test_macros.h"
22 #include "archetypes.hpp"
23 
24 using std::optional;
25 
26 struct X
27 {
28     static bool throw_now;
29 
30     X() = default;
XX31     X(int)
32     {
33         if (throw_now)
34             TEST_THROW(6);
35     }
36 };
37 
38 bool X::throw_now = false;
39 
40 struct Y1
41 {
42     Y1() = default;
Y1Y143     Y1(const int&) {}
44     Y1& operator=(const Y1&) = delete;
45 };
46 
47 struct Y2
48 {
49     Y2() = default;
50     Y2(const int&) = delete;
operator =Y251     Y2& operator=(const int&) { return *this; }
52 };
53 
54 template <class T>
55 struct AssignableFrom {
56   static int type_constructed;
57   static int type_assigned;
58 static int int_constructed;
59   static int int_assigned;
60 
resetAssignableFrom61   static void reset() {
62       type_constructed = int_constructed = 0;
63       type_assigned = int_assigned = 0;
64   }
65 
66   AssignableFrom() = default;
67 
AssignableFromAssignableFrom68   explicit AssignableFrom(T) { ++type_constructed; }
operator =AssignableFrom69   AssignableFrom& operator=(T) { ++type_assigned; return *this; }
70 
AssignableFromAssignableFrom71   AssignableFrom(int) { ++int_constructed; }
operator =AssignableFrom72   AssignableFrom& operator=(int) { ++int_assigned; return *this; }
73 private:
74   AssignableFrom(AssignableFrom const&) = delete;
75   AssignableFrom& operator=(AssignableFrom const&) = delete;
76 };
77 
78 template <class T> int AssignableFrom<T>::type_constructed = 0;
79 template <class T> int AssignableFrom<T>::type_assigned = 0;
80 template <class T> int AssignableFrom<T>::int_constructed = 0;
81 template <class T> int AssignableFrom<T>::int_assigned = 0;
82 
83 
test_with_test_type()84 void test_with_test_type() {
85     using T = TestTypes::TestType;
86     T::reset();
87     { // non-empty to empty
88         T::reset_constructors();
89         optional<T> opt;
90         const optional<int> other(42);
91         opt = other;
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>(other) == true);
98         assert(*other == 42);
99         assert(static_cast<bool>(opt) == true);
100         assert(*opt == T(42));
101     }
102     assert(T::alive == 0);
103     { // non-empty to non-empty
104         optional<T> opt(101);
105         const optional<int> other(42);
106         T::reset_constructors();
107         opt = other;
108         assert(T::alive == 1);
109         assert(T::constructed == 0);
110         assert(T::assigned == 1);
111         assert(T::value_assigned == 1);
112         assert(T::destroyed == 0);
113         assert(static_cast<bool>(other) == true);
114         assert(*other == 42);
115         assert(static_cast<bool>(opt) == true);
116         assert(*opt == T(42));
117     }
118     assert(T::alive == 0);
119     { // empty to non-empty
120         optional<T> opt(101);
121         const optional<int> other;
122         T::reset_constructors();
123         opt = other;
124         assert(T::alive == 0);
125         assert(T::constructed == 0);
126         assert(T::assigned == 0);
127         assert(T::destroyed == 1);
128         assert(static_cast<bool>(other) == false);
129         assert(static_cast<bool>(opt) == false);
130     }
131     assert(T::alive == 0);
132     { // empty to empty
133         optional<T> opt;
134         const optional<int> other;
135         T::reset_constructors();
136         opt = other;
137         assert(T::alive == 0);
138         assert(T::constructed == 0);
139         assert(T::assigned == 0);
140         assert(T::destroyed == 0);
141         assert(static_cast<bool>(other) == false);
142         assert(static_cast<bool>(opt) == false);
143     }
144     assert(T::alive == 0);
145 }
146 
test_ambigious_assign()147 void test_ambigious_assign() {
148     using OptInt = std::optional<int>;
149     {
150         using T = AssignableFrom<OptInt const&>;
151         const OptInt a(42);
152         T::reset();
153         {
154             std::optional<T> t;
155             t = a;
156             assert(T::type_constructed == 1);
157             assert(T::type_assigned == 0);
158             assert(T::int_constructed == 0);
159             assert(T::int_assigned == 0);
160         }
161         T::reset();
162         {
163             std::optional<T> t(42);
164             t = a;
165             assert(T::type_constructed == 0);
166             assert(T::type_assigned == 1);
167             assert(T::int_constructed == 1);
168             assert(T::int_assigned == 0);
169         }
170         T::reset();
171         {
172             std::optional<T> t(42);
173             t = std::move(a);
174             assert(T::type_constructed == 0);
175             assert(T::type_assigned == 1);
176             assert(T::int_constructed == 1);
177             assert(T::int_assigned == 0);
178         }
179     }
180     {
181         using T = AssignableFrom<OptInt&>;
182         OptInt a(42);
183         T::reset();
184         {
185             std::optional<T> t;
186             t = a;
187             assert(T::type_constructed == 1);
188             assert(T::type_assigned == 0);
189             assert(T::int_constructed == 0);
190             assert(T::int_assigned == 0);
191         }
192         {
193             using Opt = std::optional<T>;
194             static_assert(!std::is_assignable_v<Opt&, OptInt const&>, "");
195         }
196     }
197 }
198 
199 
main()200 int main()
201 {
202     test_with_test_type();
203     test_ambigious_assign();
204     {
205         optional<int> opt;
206         constexpr optional<short> opt2;
207         opt = opt2;
208         static_assert(static_cast<bool>(opt2) == false, "");
209         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
210     }
211     {
212         optional<int> opt;
213         constexpr optional<short> opt2(short{2});
214         opt = opt2;
215         static_assert(static_cast<bool>(opt2) == true, "");
216         static_assert(*opt2 == 2, "");
217         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
218         assert(*opt == *opt2);
219     }
220     {
221         optional<int> opt(3);
222         constexpr optional<short> opt2;
223         opt = opt2;
224         static_assert(static_cast<bool>(opt2) == false, "");
225         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
226     }
227     {
228         optional<int> opt(3);
229         constexpr optional<short> opt2(short{2});
230         opt = opt2;
231         static_assert(static_cast<bool>(opt2) == true, "");
232         static_assert(*opt2 == 2, "");
233         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
234         assert(*opt == *opt2);
235     }
236 #ifndef TEST_HAS_NO_EXCEPTIONS
237     {
238         optional<X> opt;
239         optional<int> opt2(42);
240         assert(static_cast<bool>(opt2) == true);
241         try
242         {
243             X::throw_now = true;
244             opt = opt2;
245             assert(false);
246         }
247         catch (int i)
248         {
249             assert(i == 6);
250             assert(static_cast<bool>(opt) == false);
251         }
252     }
253 #endif
254 }
255