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