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
12 // XFAIL: availability=macosx10.13
13 // XFAIL: availability=macosx10.12
14 // XFAIL: availability=macosx10.11
15 // XFAIL: availability=macosx10.10
16 // XFAIL: availability=macosx10.9
17 // XFAIL: availability=macosx10.8
18 // XFAIL: availability=macosx10.7
19
20 // <any>
21
22 // template <class ValueType>
23 // any& operator=(ValueType&&);
24
25 // Test value copy and move assignment.
26
27 #include <any>
28 #include <cassert>
29
30 #include "any_helpers.h"
31 #include "count_new.hpp"
32 #include "test_macros.h"
33
34 using std::any;
35 using std::any_cast;
36
37 template <class LHS, class RHS>
test_assign_value()38 void test_assign_value() {
39 assert(LHS::count == 0);
40 assert(RHS::count == 0);
41 LHS::reset();
42 RHS::reset();
43 {
44 any lhs(LHS(1));
45 any const rhs(RHS(2));
46
47 assert(LHS::count == 1);
48 assert(RHS::count == 1);
49 assert(RHS::copied == 0);
50
51 lhs = rhs;
52
53 assert(RHS::copied == 1);
54 assert(LHS::count == 0);
55 assert(RHS::count == 2);
56
57 assertContains<RHS>(lhs, 2);
58 assertContains<RHS>(rhs, 2);
59 }
60 assert(LHS::count == 0);
61 assert(RHS::count == 0);
62 LHS::reset();
63 RHS::reset();
64 {
65 any lhs(LHS(1));
66 any rhs(RHS(2));
67
68 assert(LHS::count == 1);
69 assert(RHS::count == 1);
70 assert(RHS::moved == 1);
71
72 lhs = std::move(rhs);
73
74 assert(RHS::moved >= 1);
75 assert(RHS::copied == 0);
76 assert(LHS::count == 0);
77 assert(RHS::count == 1 + rhs.has_value());
78 LIBCPP_ASSERT(!rhs.has_value());
79
80 assertContains<RHS>(lhs, 2);
81 if (rhs.has_value())
82 assertContains<RHS>(rhs, 0);
83 }
84 assert(LHS::count == 0);
85 assert(RHS::count == 0);
86 }
87
88 template <class RHS>
test_assign_value_empty()89 void test_assign_value_empty() {
90 assert(RHS::count == 0);
91 RHS::reset();
92 {
93 any lhs;
94 RHS rhs(42);
95 assert(RHS::count == 1);
96 assert(RHS::copied == 0);
97
98 lhs = rhs;
99
100 assert(RHS::count == 2);
101 assert(RHS::copied == 1);
102 assert(RHS::moved >= 0);
103 assertContains<RHS>(lhs, 42);
104 }
105 assert(RHS::count == 0);
106 RHS::reset();
107 {
108 any lhs;
109 RHS rhs(42);
110 assert(RHS::count == 1);
111 assert(RHS::moved == 0);
112
113 lhs = std::move(rhs);
114
115 assert(RHS::count == 2);
116 assert(RHS::copied == 0);
117 assert(RHS::moved >= 1);
118 assertContains<RHS>(lhs, 42);
119 }
120 assert(RHS::count == 0);
121 RHS::reset();
122 }
123
124
125 template <class Tp, bool Move = false>
test_assign_throws()126 void test_assign_throws() {
127 #if !defined(TEST_HAS_NO_EXCEPTIONS)
128 auto try_throw =
129 [](any& lhs, Tp& rhs) {
130 try {
131 Move ? lhs = std::move(rhs)
132 : lhs = rhs;
133 assert(false);
134 } catch (my_any_exception const &) {
135 // do nothing
136 } catch (...) {
137 assert(false);
138 }
139 };
140 // const lvalue to empty
141 {
142 any lhs;
143 Tp rhs(1);
144 assert(Tp::count == 1);
145
146 try_throw(lhs, rhs);
147
148 assert(Tp::count == 1);
149 assertEmpty<Tp>(lhs);
150 }
151 {
152 any lhs((small(2)));
153 Tp rhs(1);
154 assert(small::count == 1);
155 assert(Tp::count == 1);
156
157 try_throw(lhs, rhs);
158
159 assert(small::count == 1);
160 assert(Tp::count == 1);
161 assertContains<small>(lhs, 2);
162 }
163 {
164 any lhs((large(2)));
165 Tp rhs(1);
166 assert(large::count == 1);
167 assert(Tp::count == 1);
168
169 try_throw(lhs, rhs);
170
171 assert(large::count == 1);
172 assert(Tp::count == 1);
173 assertContains<large>(lhs, 2);
174 }
175 #endif
176 }
177
178
179 // Test that any& operator=(ValueType&&) is *never* selected for:
180 // * std::in_place type.
181 // * Non-copyable types
test_sfinae_constraints()182 void test_sfinae_constraints() {
183 { // Only the constructors are required to SFINAE on in_place_t
184 using Tag = std::in_place_type_t<int>;
185 using RawTag = std::remove_reference_t<Tag>;
186 static_assert(std::is_assignable<std::any, RawTag&&>::value, "");
187 }
188 {
189 struct Dummy { Dummy() = delete; };
190 using T = std::in_place_type_t<Dummy>;
191 static_assert(std::is_assignable<std::any, T>::value, "");
192 }
193 {
194 // Test that the ValueType&& constructor SFINAE's away when the
195 // argument is non-copyable
196 struct NoCopy {
197 NoCopy() = default;
198 NoCopy(NoCopy const&) = delete;
199 NoCopy(NoCopy&&) = default;
200 };
201 static_assert(!std::is_assignable<std::any, NoCopy>::value, "");
202 static_assert(!std::is_assignable<std::any, NoCopy&>::value, "");
203 }
204 }
205
main()206 int main() {
207 test_assign_value<small1, small2>();
208 test_assign_value<large1, large2>();
209 test_assign_value<small, large>();
210 test_assign_value<large, small>();
211 test_assign_value_empty<small>();
212 test_assign_value_empty<large>();
213 test_assign_throws<small_throws_on_copy>();
214 test_assign_throws<large_throws_on_copy>();
215 test_assign_throws<throws_on_move, /* Move = */ true>();
216 test_sfinae_constraints();
217 }
218