1 // Copyright (C) 2014 Andrzej Krzemienski.
2 //
3 // Use, modification, and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/lib/optional for documentation.
8 //
9 // You are welcome to contact the author at: akrzemi1@gmail.com
10
11
12 #include "boost/optional/optional.hpp"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #include "boost/core/addressof.hpp"
19 #include "boost/core/enable_if.hpp"
20 #include "boost/core/lightweight_test.hpp"
21 #include "testable_classes.hpp"
22
23 using boost::optional;
24 using boost::none;
25
26 struct CountingClass
27 {
28 static int count;
29 static int assign_count;
CountingClassCountingClass30 CountingClass() { ++count; }
CountingClassCountingClass31 CountingClass(const CountingClass&) { ++count; }
operator =CountingClass32 CountingClass& operator=(const CountingClass&) { ++assign_count; return *this; }
~CountingClassCountingClass33 ~CountingClass() { ++count; }
34 };
35
36 int CountingClass::count = 0;
37 int CountingClass::assign_count = 0;
38
test_no_object_creation()39 void test_no_object_creation()
40 {
41 BOOST_TEST_EQ(0, CountingClass::count);
42 BOOST_TEST_EQ(0, CountingClass::assign_count);
43 {
44 CountingClass v1, v2;
45 optional<CountingClass&> oA(v1);
46 optional<CountingClass&> oB;
47 optional<CountingClass&> oC = oA;
48 oB = oA;
49 *oB = v2;
50 oC = none;
51 oC = optional<CountingClass&>(v2);
52 oB = none;
53 oA = oB;
54 }
55 BOOST_TEST_EQ(4, CountingClass::count);
56 BOOST_TEST_EQ(1, CountingClass::assign_count);
57 }
58
59 template <typename T>
60 typename boost::enable_if< has_arrow<T> >::type
test_arrow_const()61 test_arrow_const()
62 {
63 const typename concrete_type_of<T>::type v(2);
64 optional<const T&> o(v);
65 BOOST_TEST(o);
66 BOOST_TEST_EQ(o->val(), 2);
67 BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
68 }
69
70 template <typename T>
71 typename boost::disable_if< has_arrow<T> >::type
test_arrow_const()72 test_arrow_const()
73 {
74 }
75
76 template <typename T>
77 typename boost::enable_if< has_arrow<T> >::type
test_arrow_noconst_const()78 test_arrow_noconst_const()
79 {
80 typename concrete_type_of<T>::type v(2);
81 optional<const T&> o(v);
82 BOOST_TEST(o);
83 BOOST_TEST_EQ(o->val(), 2);
84 BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
85
86 v.val() = 1;
87 BOOST_TEST(o);
88 BOOST_TEST_EQ(o->val(), 1);
89 BOOST_TEST_EQ(v.val(), 1);
90 BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
91 }
92
93 template <typename T>
94 typename boost::disable_if< has_arrow<T> >::type
test_arrow_noconst_const()95 test_arrow_noconst_const()
96 {
97 }
98
99 template <typename T>
100 typename boost::enable_if< has_arrow<T> >::type
test_arrow()101 test_arrow()
102 {
103 typename concrete_type_of<T>::type v(2);
104 optional<T&> o(v);
105 BOOST_TEST(o);
106 BOOST_TEST_EQ(o->val(), 2);
107 BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
108
109 v.val() = 1;
110 BOOST_TEST(o);
111 BOOST_TEST_EQ(o->val(), 1);
112 BOOST_TEST_EQ(v.val(), 1);
113 BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
114
115 o->val() = 3;
116 BOOST_TEST(o);
117 BOOST_TEST_EQ(o->val(), 3);
118 BOOST_TEST_EQ(v.val(), 3);
119 BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
120
121 }
122
123 template <typename T>
124 typename boost::disable_if< has_arrow<T> >::type
test_arrow()125 test_arrow()
126 {
127 }
128
129 template <typename T>
test_not_containing_value_for()130 void test_not_containing_value_for()
131 {
132 optional<T&> o1;
133 optional<T&> o2 = none;
134 optional<T&> o3 = o1;
135
136 BOOST_TEST(!o1);
137 BOOST_TEST(!o2);
138 BOOST_TEST(!o3);
139
140 BOOST_TEST(o1 == none);
141 BOOST_TEST(o2 == none);
142 BOOST_TEST(o3 == none);
143 }
144
145 template <typename T>
test_direct_init_for_const()146 void test_direct_init_for_const()
147 {
148 const typename concrete_type_of<T>::type v(2);
149 optional<const T&> o(v);
150
151 BOOST_TEST(o);
152 BOOST_TEST(o != none);
153 BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
154 BOOST_TEST_EQ(val(*o), val(v));
155 BOOST_TEST_EQ(val(*o), 2);
156 }
157
158 template <typename T>
test_direct_init_for_noconst_const()159 void test_direct_init_for_noconst_const()
160 {
161 typename concrete_type_of<T>::type v(2);
162 optional<const T&> o(v);
163
164 BOOST_TEST(o);
165 BOOST_TEST(o != none);
166 BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
167 BOOST_TEST_EQ(val(*o), val(v));
168 BOOST_TEST_EQ(val(*o), 2);
169
170 val(v) = 9;
171 BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
172 BOOST_TEST_EQ(val(*o), val(v));
173 BOOST_TEST_EQ(val(*o), 9);
174 BOOST_TEST_EQ(val(v), 9);
175 }
176
177 template <typename T>
test_direct_init_for()178 void test_direct_init_for()
179 {
180 typename concrete_type_of<T>::type v(2);
181 optional<T&> o(v);
182
183 BOOST_TEST(o);
184 BOOST_TEST(o != none);
185 BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
186 BOOST_TEST_EQ(val(*o), val(v));
187 BOOST_TEST_EQ(val(*o), 2);
188
189 val(v) = 9;
190 BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
191 BOOST_TEST_EQ(val(*o), val(v));
192 BOOST_TEST_EQ(val(*o), 9);
193 BOOST_TEST_EQ(val(v), 9);
194
195 val(*o) = 7;
196 BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
197 BOOST_TEST_EQ(val(*o), val(v));
198 BOOST_TEST_EQ(val(*o), 7);
199 BOOST_TEST_EQ(val(v), 7);
200 }
201
202 template <typename T, typename U>
test_clearing_the_value()203 void test_clearing_the_value()
204 {
205 typename concrete_type_of<T>::type v(2);
206 optional<U&> o1(v), o2(v);
207
208 BOOST_TEST(o1);
209 BOOST_TEST(o1 != none);
210 BOOST_TEST(o2);
211 BOOST_TEST(o2 != none);
212
213 o1 = none;
214 BOOST_TEST(!o1);
215 BOOST_TEST(o1 == none);
216 BOOST_TEST(o2);
217 BOOST_TEST(o2 != none);
218 BOOST_TEST_EQ(val(*o2), 2);
219 BOOST_TEST(boost::addressof(*o2) == boost::addressof(v));
220 BOOST_TEST_EQ(val(v), 2);
221 }
222
223 template <typename T, typename U>
test_equality()224 void test_equality()
225 {
226 typename concrete_type_of<T>::type v1(1), v2(2), v2_(2), v3(3);
227 optional<U&> o1(v1), o2(v2), o2_(v2_), o3(v3), o3_(v3), oN, oN_;
228 // o2 and o2_ point to different objects; o3 and o3_ point to the same object
229
230 BOOST_TEST(oN == oN);
231 BOOST_TEST(oN == oN_);
232 BOOST_TEST(oN_ == oN);
233 BOOST_TEST(o1 == o1);
234 BOOST_TEST(o2 == o2);
235 BOOST_TEST(o2 == o2_);
236 BOOST_TEST(o2_ == o2);
237 BOOST_TEST(o3 == o3);
238 BOOST_TEST(o3 == o3_);
239 BOOST_TEST(!(oN == o1));
240 BOOST_TEST(!(o1 == oN));
241 BOOST_TEST(!(o2 == o1));
242 BOOST_TEST(!(o2 == oN));
243
244 BOOST_TEST(!(oN != oN));
245 BOOST_TEST(!(oN != oN_));
246 BOOST_TEST(!(oN_ != oN));
247 BOOST_TEST(!(o1 != o1));
248 BOOST_TEST(!(o2 != o2));
249 BOOST_TEST(!(o2 != o2_));
250 BOOST_TEST(!(o2_ != o2));
251 BOOST_TEST(!(o3 != o3));
252 BOOST_TEST(!(o3 != o3_));
253 BOOST_TEST( (oN != o1));
254 BOOST_TEST( (o1 != oN));
255 BOOST_TEST( (o2 != o1));
256 BOOST_TEST( (o2 != oN));
257 }
258
259 template <typename T, typename U>
test_order()260 void test_order()
261 {
262 typename concrete_type_of<T>::type v1(1), v2(2), v2_(2), v3(3);
263 optional<U&> o1(v1), o2(v2), o2_(v2_), o3(v3), o3_(v3), oN, oN_;
264 // o2 and o2_ point to different objects; o3 and o3_ point to the same object
265
266 BOOST_TEST(!(oN < oN));
267 BOOST_TEST(!(oN < oN_));
268 BOOST_TEST(!(oN_ < oN));
269 BOOST_TEST(!(o1 < o1));
270 BOOST_TEST(!(o2 < o2));
271 BOOST_TEST(!(o2 < o2_));
272 BOOST_TEST(!(o2_ < o2));
273 BOOST_TEST(!(o3 < o3));
274 BOOST_TEST(!(o3 < o3_));
275
276 BOOST_TEST( (oN <= oN));
277 BOOST_TEST( (oN <= oN_));
278 BOOST_TEST( (oN_ <= oN));
279 BOOST_TEST( (o1 <= o1));
280 BOOST_TEST( (o2 <= o2));
281 BOOST_TEST( (o2 <= o2_));
282 BOOST_TEST( (o2_ <= o2));
283 BOOST_TEST( (o3 <= o3));
284 BOOST_TEST( (o3 <= o3_));
285
286 BOOST_TEST(!(oN > oN));
287 BOOST_TEST(!(oN > oN_));
288 BOOST_TEST(!(oN_ > oN));
289 BOOST_TEST(!(o1 > o1));
290 BOOST_TEST(!(o2 > o2));
291 BOOST_TEST(!(o2 > o2_));
292 BOOST_TEST(!(o2_ > o2));
293 BOOST_TEST(!(o3 > o3));
294 BOOST_TEST(!(o3 > o3_));
295
296 BOOST_TEST( (oN >= oN));
297 BOOST_TEST( (oN >= oN_));
298 BOOST_TEST( (oN_ >= oN));
299 BOOST_TEST( (o1 >= o1));
300 BOOST_TEST( (o2 >= o2));
301 BOOST_TEST( (o2 >= o2_));
302 BOOST_TEST( (o2_ >= o2));
303 BOOST_TEST( (o3 >= o3));
304 BOOST_TEST( (o3 >= o3_));
305
306 BOOST_TEST( (oN < o1));
307 BOOST_TEST( (oN_ < o1));
308 BOOST_TEST( (oN < o2));
309 BOOST_TEST( (oN_ < o2));
310 BOOST_TEST( (oN < o2_));
311 BOOST_TEST( (oN_ < o2_));
312 BOOST_TEST( (oN < o3));
313 BOOST_TEST( (oN_ < o3));
314 BOOST_TEST( (oN < o3_));
315 BOOST_TEST( (oN_ < o3_));
316 BOOST_TEST( (o1 < o2));
317 BOOST_TEST( (o1 < o2_));
318 BOOST_TEST( (o1 < o3));
319 BOOST_TEST( (o1 < o3_));
320 BOOST_TEST( (o2 < o3));
321 BOOST_TEST( (o2_ < o3));
322 BOOST_TEST( (o2 < o3_));
323 BOOST_TEST( (o2_ < o3_));
324
325 BOOST_TEST( (oN <= o1));
326 BOOST_TEST( (oN_ <= o1));
327 BOOST_TEST( (oN <= o2));
328 BOOST_TEST( (oN_ <= o2));
329 BOOST_TEST( (oN <= o2_));
330 BOOST_TEST( (oN_ <= o2_));
331 BOOST_TEST( (oN <= o3));
332 BOOST_TEST( (oN_ <= o3));
333 BOOST_TEST( (oN <= o3_));
334 BOOST_TEST( (oN_ <= o3_));
335 BOOST_TEST( (o1 <= o2));
336 BOOST_TEST( (o1 <= o2_));
337 BOOST_TEST( (o1 <= o3));
338 BOOST_TEST( (o1 <= o3_));
339 BOOST_TEST( (o2 <= o3));
340 BOOST_TEST( (o2_ <= o3));
341 BOOST_TEST( (o2 <= o3_));
342 BOOST_TEST( (o2_ <= o3_));
343
344 BOOST_TEST(!(oN > o1));
345 BOOST_TEST(!(oN_ > o1));
346 BOOST_TEST(!(oN > o2));
347 BOOST_TEST(!(oN_ > o2));
348 BOOST_TEST(!(oN > o2_));
349 BOOST_TEST(!(oN_ > o2_));
350 BOOST_TEST(!(oN > o3));
351 BOOST_TEST(!(oN_ > o3));
352 BOOST_TEST(!(oN > o3_));
353 BOOST_TEST(!(oN_ > o3_));
354 BOOST_TEST(!(o1 > o2));
355 BOOST_TEST(!(o1 > o2_));
356 BOOST_TEST(!(o1 > o3));
357 BOOST_TEST(!(o1 > o3_));
358 BOOST_TEST(!(o2 > o3));
359 BOOST_TEST(!(o2_ > o3));
360 BOOST_TEST(!(o2 > o3_));
361 BOOST_TEST(!(o2_ > o3_));
362
363 BOOST_TEST(!(oN >= o1));
364 BOOST_TEST(!(oN_ >= o1));
365 BOOST_TEST(!(oN >= o2));
366 BOOST_TEST(!(oN_ >= o2));
367 BOOST_TEST(!(oN >= o2_));
368 BOOST_TEST(!(oN_ >= o2_));
369 BOOST_TEST(!(oN >= o3));
370 BOOST_TEST(!(oN_ >= o3));
371 BOOST_TEST(!(oN >= o3_));
372 BOOST_TEST(!(oN_ >= o3_));
373 BOOST_TEST(!(o1 >= o2));
374 BOOST_TEST(!(o1 >= o2_));
375 BOOST_TEST(!(o1 >= o3));
376 BOOST_TEST(!(o1 >= o3_));
377 BOOST_TEST(!(o2 >= o3));
378 BOOST_TEST(!(o2_ >= o3));
379 BOOST_TEST(!(o2 >= o3_));
380 BOOST_TEST(!(o2_ >= o3_));
381
382 BOOST_TEST(!(o1 < oN));
383 BOOST_TEST(!(o1 < oN_));
384 BOOST_TEST(!(o2 < oN));
385 BOOST_TEST(!(o2 < oN_));
386 BOOST_TEST(!(o2_ < oN));
387 BOOST_TEST(!(o2_ < oN_));
388 BOOST_TEST(!(o3 < oN));
389 BOOST_TEST(!(o3 < oN_));
390 BOOST_TEST(!(o3_ < oN));
391 BOOST_TEST(!(o3_ < oN_));
392 BOOST_TEST(!(o2 < oN));
393 BOOST_TEST(!(o2_ < oN_));
394 BOOST_TEST(!(o3 < oN));
395 BOOST_TEST(!(o3_ < oN_));
396 BOOST_TEST(!(o3 < oN));
397 BOOST_TEST(!(o3 < oN_));
398 BOOST_TEST(!(o3_ < oN));
399 BOOST_TEST(!(o3_ < oN_));
400 }
401
402 template <typename T, typename U>
test_swap()403 void test_swap()
404 {
405 typename concrete_type_of<T>::type v1(1), v2(2);
406 optional<U&> o1(v1), o1_(v1), o2(v2), o2_(v2), oN, oN_;
407
408 swap(o1, o1);
409 BOOST_TEST(o1);
410 BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1));
411
412 swap(oN, oN_);
413 BOOST_TEST(!oN);
414 BOOST_TEST(!oN_);
415
416 swap(o1, oN);
417 BOOST_TEST(!o1);
418 BOOST_TEST(oN);
419 BOOST_TEST(boost::addressof(*oN) == boost::addressof(v1));
420
421 swap(oN, o1);
422 BOOST_TEST(!oN);
423 BOOST_TEST(o1);
424 BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1));
425
426 swap(o1_, o2_);
427 BOOST_TEST(o1_);
428 BOOST_TEST(o2_);
429 BOOST_TEST(boost::addressof(*o1_) == boost::addressof(v2));
430 BOOST_TEST(boost::addressof(*o2_) == boost::addressof(v1));
431 }
432
433 template <typename T, typename U>
test_convertability_of_compatible_reference_types()434 void test_convertability_of_compatible_reference_types()
435 {
436 typename concrete_type_of<T>::type v1(1);
437 optional<T&> oN, o1(v1);
438 optional<U&> uN(oN), u1(o1);
439 BOOST_TEST(!uN);
440 BOOST_TEST(u1);
441 BOOST_TEST(boost::addressof(*u1) == boost::addressof(*o1));
442
443 uN = o1;
444 u1 = oN;
445 BOOST_TEST(!u1);
446 BOOST_TEST(uN);
447 BOOST_TEST(boost::addressof(*uN) == boost::addressof(*o1));
448 }
449
450 template <typename T>
test_optional_ref()451 void test_optional_ref()
452 {
453 test_not_containing_value_for<T>();
454 test_direct_init_for<T>();
455 test_clearing_the_value<T, T>();
456 test_arrow<T>();
457 test_equality<T, T>();
458 test_order<T, T>();
459 test_swap<T, T>();
460 }
461
462 template <typename T>
test_optional_const_ref()463 void test_optional_const_ref()
464 {
465 test_not_containing_value_for<const T>();
466 test_direct_init_for_const<T>();
467 test_direct_init_for_noconst_const<T>();
468 test_clearing_the_value<const T, const T>();
469 test_clearing_the_value<T, const T>();
470 test_arrow_const<T>();
471 test_arrow_noconst_const<T>();
472 test_equality<const T, const T>();
473 test_equality<T, const T>();
474 test_order<const T, const T>();
475 test_order<T, const T>();
476 test_swap<const T, const T>();
477 test_swap<T, const T>();
478 }
479
main()480 int main()
481 {
482 test_optional_ref<int>();
483 test_optional_ref<ScopeGuard>();
484 test_optional_ref<Abstract>();
485 test_optional_ref< optional<int> >();
486
487 test_optional_const_ref<int>();
488 test_optional_const_ref<ScopeGuard>();
489 test_optional_const_ref<Abstract>();
490 test_optional_const_ref< optional<int> >();
491
492 test_convertability_of_compatible_reference_types<int, const int>();
493 test_convertability_of_compatible_reference_types<Impl, Abstract>();
494 test_convertability_of_compatible_reference_types<Impl, const Abstract>();
495 test_convertability_of_compatible_reference_types<const Impl, const Abstract>();
496 test_convertability_of_compatible_reference_types<optional<int>, const optional<int> >();
497
498 return boost::report_errors();
499 }
500