• 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 
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