]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/optional/test/optional_test_swap.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / optional / test / optional_test_swap.cpp
1 // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
2 // Copyright (C) 2015 Andrzej Krzemienski.
3 //
4 // Use, modification, and distribution is subject to the Boost Software
5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/lib/optional for documentation.
9 //
10 // You are welcome to contact the author at:
11 // fernando_cacciola@hotmail.com
12 //
13 // Revisions:
14 // 12 May 2008 (added more swap tests)
15 //
16
17 #include "boost/optional/optional.hpp"
18 #include "boost/utility/in_place_factory.hpp"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #include "boost/core/lightweight_test.hpp"
25
26 #if __cplusplus < 201103L
27 #include <algorithm>
28 #else
29 #include <utility>
30 #endif
31
32 using boost::optional;
33 using boost::none;
34
35 #define ARG(T) (static_cast< T const* >(0))
36
37 namespace optional_swap_test
38 {
39 class default_ctor_exception : public std::exception {} ;
40 class copy_ctor_exception : public std::exception {} ;
41 class assignment_exception : public std::exception {} ;
42
43 //
44 // Base class for swap test classes. Its assignment should not be called, when swapping
45 // optional<T> objects. (The default std::swap would do so.)
46 //
47 class base_class_with_forbidden_assignment
48 {
49 public:
50 base_class_with_forbidden_assignment & operator=(const base_class_with_forbidden_assignment &)
51 {
52 BOOST_TEST(!"The assignment should not be used while swapping!");
53 throw assignment_exception();
54 }
55
56 virtual ~base_class_with_forbidden_assignment() {}
57 };
58
59 //
60 // Class without default constructor
61 //
62 class class_without_default_ctor : public base_class_with_forbidden_assignment
63 {
64 public:
65 char data;
66 explicit class_without_default_ctor(char arg) : data(arg) {}
67 };
68
69 //
70 // Class whose default constructor should not be used by optional::swap!
71 //
72 class class_whose_default_ctor_should_not_be_used : public base_class_with_forbidden_assignment
73 {
74 public:
75 char data;
76 explicit class_whose_default_ctor_should_not_be_used(char arg) : data(arg) {}
77
78 class_whose_default_ctor_should_not_be_used()
79 {
80 BOOST_TEST(!"This default constructor should not be used while swapping!");
81 throw default_ctor_exception();
82 }
83 };
84
85 //
86 // Class whose default constructor should be used by optional::swap.
87 // Its copy constructor should be avoided!
88 //
89 class class_whose_default_ctor_should_be_used : public base_class_with_forbidden_assignment
90 {
91 public:
92 char data;
93 explicit class_whose_default_ctor_should_be_used(char arg) : data(arg) { }
94
95 class_whose_default_ctor_should_be_used() : data('\0') { }
96
97 class_whose_default_ctor_should_be_used(const class_whose_default_ctor_should_be_used &)
98 {
99 BOOST_TEST(!"This copy constructor should not be used while swapping!");
100 throw copy_ctor_exception();
101 }
102 };
103
104 //
105 // Class template whose default constructor should be used by optional::swap.
106 // Its copy constructor should be avoided!
107 //
108 template <class T>
109 class template_whose_default_ctor_should_be_used : public base_class_with_forbidden_assignment
110 {
111 public:
112 T data;
113 explicit template_whose_default_ctor_should_be_used(T arg) : data(arg) { }
114
115 template_whose_default_ctor_should_be_used() : data('\0') { }
116
117 template_whose_default_ctor_should_be_used(const template_whose_default_ctor_should_be_used &)
118 {
119 BOOST_TEST(!"This copy constructor should not be used while swapping!");
120 throw copy_ctor_exception();
121 }
122 };
123
124 //
125 // Class whose explicit constructor should be used by optional::swap.
126 // Its other constructors should be avoided!
127 //
128 class class_whose_explicit_ctor_should_be_used : public base_class_with_forbidden_assignment
129 {
130 public:
131 char data;
132 explicit class_whose_explicit_ctor_should_be_used(char arg) : data(arg) { }
133
134 class_whose_explicit_ctor_should_be_used()
135 {
136 BOOST_TEST(!"This default constructor should not be used while swapping!");
137 throw default_ctor_exception();
138 }
139
140 class_whose_explicit_ctor_should_be_used(const class_whose_explicit_ctor_should_be_used &)
141 {
142 BOOST_TEST(!"This copy constructor should not be used while swapping!");
143 throw copy_ctor_exception();
144 }
145 };
146
147 void swap(class_whose_default_ctor_should_not_be_used & lhs, class_whose_default_ctor_should_not_be_used & rhs)
148 {
149 std::swap(lhs.data, rhs.data);
150 }
151
152 void swap(class_whose_default_ctor_should_be_used & lhs, class_whose_default_ctor_should_be_used & rhs)
153 {
154 std::swap(lhs.data, rhs.data);
155 }
156
157 void swap(class_without_default_ctor & lhs, class_without_default_ctor & rhs)
158 {
159 std::swap(lhs.data, rhs.data);
160 }
161
162 void swap(class_whose_explicit_ctor_should_be_used & lhs, class_whose_explicit_ctor_should_be_used & rhs)
163 {
164 std::swap(lhs.data, rhs.data);
165 }
166
167 template <class T>
168 void swap(template_whose_default_ctor_should_be_used<T> & lhs, template_whose_default_ctor_should_be_used<T> & rhs)
169 {
170 std::swap(lhs.data, rhs.data);
171 }
172
173 //
174 // optional<T>::swap should be customized when neither the copy constructor
175 // nor the default constructor of T are supposed to be used when swapping, e.g.,
176 // for the following type T = class_whose_explicit_ctor_should_be_used.
177 //
178 void swap(boost::optional<class_whose_explicit_ctor_should_be_used> & x, boost::optional<class_whose_explicit_ctor_should_be_used> & y)
179 {
180 bool hasX(x);
181 bool hasY(y);
182
183 if ( !hasX && !hasY )
184 return;
185
186 if( !hasX )
187 x = boost::in_place('\0');
188 else if ( !hasY )
189 y = boost::in_place('\0');
190
191 optional_swap_test::swap(*x,*y);
192
193 if( !hasX )
194 y = boost::none ;
195 else if( !hasY )
196 x = boost::none ;
197 }
198
199
200 } // End of namespace optional_swap_test.
201
202
203 namespace boost {
204
205 //
206 // Compile time tweaking on whether or not swap should use the default constructor:
207 //
208
209 template <> struct optional_swap_should_use_default_constructor<
210 optional_swap_test::class_whose_default_ctor_should_be_used> : true_type {} ;
211
212 template <> struct optional_swap_should_use_default_constructor<
213 optional_swap_test::class_whose_default_ctor_should_not_be_used> : false_type {} ;
214
215 template <class T> struct optional_swap_should_use_default_constructor<
216 optional_swap_test::template_whose_default_ctor_should_be_used<T> > : true_type {} ;
217
218
219 //
220 // Specialization of boost::swap:
221 //
222 template <>
223 void swap(optional<optional_swap_test::class_whose_explicit_ctor_should_be_used> & x, optional<optional_swap_test::class_whose_explicit_ctor_should_be_used> & y)
224 {
225 optional_swap_test::swap(x, y);
226 }
227
228 } // namespace boost
229
230
231 namespace std {
232
233 //
234 // Specializations of std::swap:
235 //
236
237 template <>
238 void swap(optional_swap_test::class_whose_default_ctor_should_be_used & x, optional_swap_test::class_whose_default_ctor_should_be_used & y)
239 {
240 optional_swap_test::swap(x, y);
241 }
242
243 template <>
244 void swap(optional_swap_test::class_whose_default_ctor_should_not_be_used & x, optional_swap_test::class_whose_default_ctor_should_not_be_used & y)
245 {
246 optional_swap_test::swap(x, y);
247 }
248
249 template <>
250 void swap(optional_swap_test::class_without_default_ctor & x, optional_swap_test::class_without_default_ctor & y)
251 {
252 optional_swap_test::swap(x, y);
253 }
254
255 template <>
256 void swap(optional_swap_test::class_whose_explicit_ctor_should_be_used & x, optional_swap_test::class_whose_explicit_ctor_should_be_used & y)
257 {
258 optional_swap_test::swap(x, y);
259 }
260
261 } // namespace std
262
263
264 //
265 // Tests whether the swap function works properly for optional<T>.
266 // Assumes that T has one data member, of type char.
267 // Returns true iff the test is passed.
268 //
269 template <class T>
270 void test_swap_function( T const* )
271 {
272 try
273 {
274 optional<T> obj1;
275 optional<T> obj2('a');
276
277 // Self-swap should not have any effect.
278 swap(obj1, obj1);
279 swap(obj2, obj2);
280 BOOST_TEST(!obj1);
281 BOOST_TEST(!!obj2 && obj2->data == 'a');
282
283 // Call non-member swap.
284 swap(obj1, obj2);
285
286 // Test if obj1 and obj2 are really swapped.
287 BOOST_TEST(!!obj1 && obj1->data == 'a');
288 BOOST_TEST(!obj2);
289
290 // Call non-member swap one more time.
291 swap(obj1, obj2);
292
293 // Test if obj1 and obj2 are swapped back.
294 BOOST_TEST(!obj1);
295 BOOST_TEST(!!obj2 && obj2->data == 'a');
296 }
297 catch(const std::exception &)
298 {
299 // The swap function should not throw, for our test cases.
300 BOOST_TEST(!"throw in swap");
301 }
302 }
303
304 //
305 // Tests whether the optional<T>::swap member function works properly.
306 // Assumes that T has one data member, of type char.
307 // Returns true iff the test is passed.
308 //
309 template <class T>
310 void test_swap_member_function( T const* )
311 {
312 try
313 {
314 optional<T> obj1;
315 optional<T> obj2('a');
316
317 // Self-swap should not have any effect.
318 obj1.swap(obj1);
319 obj2.swap(obj2);
320 BOOST_TEST(!obj1);
321 BOOST_TEST(!!obj2 && obj2->data == 'a');
322
323 // Call member swap.
324 obj1.swap(obj2);
325
326 // Test if obj1 and obj2 are really swapped.
327 BOOST_TEST(!!obj1 && obj1->data == 'a');
328 BOOST_TEST(!obj2);
329
330 // Call member swap one more time.
331 obj1.swap(obj2);
332
333 // Test if obj1 and obj2 are swapped back.
334 BOOST_TEST(!obj1);
335 BOOST_TEST(!!obj2 && obj2->data == 'a');
336 }
337 catch(const std::exception &)
338 {
339 BOOST_TEST(!"throw in swap");
340 }
341 }
342
343
344 //
345 // Tests compile time tweaking of swap, by means of
346 // optional_swap_should_use_default_constructor.
347 //
348 void test_swap_tweaking()
349 {
350 ( test_swap_function( ARG(optional_swap_test::class_without_default_ctor) ) );
351 ( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
352 ( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
353 ( test_swap_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
354 ( test_swap_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
355 ( test_swap_member_function( ARG(optional_swap_test::class_without_default_ctor) ) );
356 ( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
357 ( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
358 ( test_swap_member_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
359 ( test_swap_member_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
360 }
361
362 int main()
363 {
364 test_swap_tweaking();
365 return boost::report_errors();
366 }