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