]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/optional/test/optional_test.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / optional / test / optional_test.cpp
1 // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
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:
10 // fernando_cacciola@hotmail.com
11 //
12 // Revisions:
13 // 12 May 2008 (added more swap tests)
14 //
15 #ifndef BOOST_NO_IOSTREAM
16 #include<iostream>
17 #endif // BOOST_NO_IOSTREAM
18 #include<stdexcept>
19 #include<string>
20
21 #define BOOST_ENABLE_ASSERT_HANDLER
22
23 #include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
24 #include "boost/mpl/bool.hpp"
25 #include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_
26
27 #include "boost/optional/optional.hpp"
28
29 #ifdef BOOST_BORLANDC
30 #pragma hdrstop
31 #endif
32
33 #include "boost/none.hpp"
34
35 #include "boost/core/lightweight_test.hpp"
36
37 #include "optional_test_common.hpp"
38
39 void test_implicit_construction ( optional<double> opt, double v, double z )
40 {
41 check_value(opt,v,z);
42 }
43
44 void test_implicit_construction ( optional<X> opt, X const& v, X const& z )
45 {
46 check_value(opt,v,z);
47 }
48
49 void test_default_implicit_construction ( double, optional<double> opt )
50 {
51 BOOST_TEST(!opt);
52 }
53
54 void test_default_implicit_construction ( X const&, optional<X> opt )
55 {
56 BOOST_TEST(!opt);
57 }
58
59 //
60 // Basic test.
61 // Check ordinary functionality:
62 // Initialization, assignment, comparison and value-accessing.
63 //
64 template<class T>
65 void test_basics( T const* )
66 {
67 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
68
69 T z(0);
70
71 T a(1);
72
73 // Default construction.
74 // 'def' state is Uninitialized.
75 // T::T() is not called (and it is not even defined)
76 optional<T> def ;
77 check_uninitialized(def);
78
79 // Implicit construction
80 // The first parameter is implicitely converted to optional<T>(a);
81 test_implicit_construction(a,a,z);
82
83 // Direct initialization.
84 // 'oa' state is Initialized with 'a'
85 // T::T( T const& x ) is used.
86 set_pending_copy( ARG(T) ) ;
87 optional<T> oa ( a ) ;
88 check_is_not_pending_copy( ARG(T) );
89 check_initialized(oa);
90 check_value(oa,a,z);
91
92 T b(2);
93
94 optional<T> ob ;
95
96 // Value-Assignment upon Uninitialized optional.
97 // T::T( T const& x ) is used.
98 set_pending_copy( ARG(T) ) ;
99 ob = a ;
100 check_is_not_pending_copy( ARG(T) ) ;
101 check_initialized(ob);
102 check_value(ob,a,z);
103
104 // Value-Assignment upon Initialized optional.
105 // T::operator=( T const& x ) is used
106 set_pending_assign( ARG(T) ) ;
107 set_pending_copy ( ARG(T) ) ;
108 set_pending_dtor ( ARG(T) ) ;
109 ob = b ;
110 check_is_not_pending_assign( ARG(T) ) ;
111 check_is_pending_copy ( ARG(T) ) ;
112 check_is_pending_dtor ( ARG(T) ) ;
113 check_initialized(ob);
114 check_value(ob,b,z);
115
116 // Assignment initialization.
117 // T::T ( T const& x ) is used to copy new value.
118 set_pending_copy( ARG(T) ) ;
119 optional<T> const oa2 ( oa ) ;
120 check_is_not_pending_copy( ARG(T) ) ;
121 check_initialized_const(oa2);
122 check_value_const(oa2,a,z);
123
124 // Assignment
125 // T::operator= ( T const& x ) is used to copy new value.
126 set_pending_assign( ARG(T) ) ;
127 oa = ob ;
128 check_is_not_pending_assign( ARG(T) ) ;
129 check_initialized(oa);
130 check_value(oa,b,z);
131
132 // Uninitializing Assignment upon Initialized Optional
133 // T::~T() is used to destroy previous value in oa.
134 set_pending_dtor( ARG(T) ) ;
135 set_pending_copy( ARG(T) ) ;
136 oa = def ;
137 check_is_not_pending_dtor( ARG(T) ) ;
138 check_is_pending_copy ( ARG(T) ) ;
139 check_uninitialized(oa);
140
141 // Uninitializing Assignment upon Uninitialized Optional
142 // (Dtor is not called this time)
143 set_pending_dtor( ARG(T) ) ;
144 set_pending_copy( ARG(T) ) ;
145 oa = def ;
146 check_is_pending_dtor( ARG(T) ) ;
147 check_is_pending_copy( ARG(T) ) ;
148 check_uninitialized(oa);
149
150 // Deinitialization of Initialized Optional
151 // T::~T() is used to destroy previous value in ob.
152 set_pending_dtor( ARG(T) ) ;
153 ob.reset();
154 check_is_not_pending_dtor( ARG(T) ) ;
155 check_uninitialized(ob);
156
157 // Deinitialization of Uninitialized Optional
158 // (Dtor is not called this time)
159 set_pending_dtor( ARG(T) ) ;
160 ob.reset();
161 check_is_pending_dtor( ARG(T) ) ;
162 check_uninitialized(ob);
163
164 }
165
166 template<class T>
167 void test_conditional_ctor_and_get_valur_or ( T const* )
168 {
169 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
170
171 T a(321);
172
173 T z(123);
174
175 optional<T> const cdef0(false,a);
176
177 optional<T> def0(false,a);
178 optional<T> def1 = boost::make_optional(false,a); // T is not within boost so ADL won't find make_optional unqualified
179 check_uninitialized(def0);
180 check_uninitialized(def1);
181
182 optional<T> const co0(true,a);
183
184 optional<T> o0(true,a);
185 optional<T> o1 = boost::make_optional(true,a); // T is not within boost so ADL won't find make_optional unqualified
186
187 check_initialized(o0);
188 check_initialized(o1);
189 check_value(o0,a,z);
190 check_value(o1,a,z);
191
192 T b = def0.get_value_or(z);
193 BOOST_TEST( b == z ) ;
194
195 b = get_optional_value_or(def0,z);
196 BOOST_TEST( b == z ) ;
197
198 b = o0.get_value_or(z);
199 BOOST_TEST( b == a ) ;
200
201 b = get_optional_value_or(o0,z);
202 BOOST_TEST( b == a ) ;
203
204
205 T const& crz = z ;
206 T& rz = z ;
207
208 T const& crzz = def0.get_value_or(crz);
209 BOOST_TEST( crzz == crz ) ;
210
211 T& rzz = def0.get_value_or(rz);
212 BOOST_TEST( rzz == rz ) ;
213
214 T const& crzzz = get_optional_value_or(cdef0,crz);
215 BOOST_TEST( crzzz == crz ) ;
216
217 T& rzzz = get_optional_value_or(def0,rz);
218 BOOST_TEST( rzzz == rz ) ;
219
220 T const& crb = o0.get_value_or(crz);
221 BOOST_TEST( crb == a ) ;
222
223 T& rb = o0.get_value_or(rz);
224 BOOST_TEST( rb == b ) ;
225
226 T const& crbb = get_optional_value_or(co0,crz);
227 BOOST_TEST( crbb == b ) ;
228
229 T const& crbbb = get_optional_value_or(o0,crz);
230 BOOST_TEST( crbbb == b ) ;
231
232 T& rbb = get_optional_value_or(o0,rz);
233 BOOST_TEST( rbb == b ) ;
234
235 T& ra = a ;
236
237 optional<T&> defref(false,ra);
238 BOOST_TEST(!defref);
239
240 optional<T&> ref(true,ra);
241 BOOST_TEST(!!ref);
242
243 a = T(432);
244
245 BOOST_TEST( *ref == a ) ;
246
247 T& r1 = defref.get_value_or(z);
248 BOOST_TEST( r1 == z ) ;
249
250 T& r2 = ref.get_value_or(z);
251 BOOST_TEST( r2 == a ) ;
252 }
253
254 //
255 // Test Direct Value Manipulation
256 //
257 template<class T>
258 void test_direct_value_manip( T const* )
259 {
260 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
261
262 T x(3);
263
264 optional<T> const c_opt0(x) ;
265 optional<T> opt0(x);
266
267 BOOST_TEST( c_opt0.get().V() == x.V() ) ;
268 BOOST_TEST( opt0.get().V() == x.V() ) ;
269
270 BOOST_TEST( c_opt0->V() == x.V() ) ;
271 BOOST_TEST( opt0->V() == x.V() ) ;
272
273 BOOST_TEST( (*c_opt0).V() == x.V() ) ;
274 BOOST_TEST( (* opt0).V() == x.V() ) ;
275
276 T y(4);
277 opt0 = y ;
278 BOOST_TEST( get(opt0).V() == y.V() ) ;
279 }
280
281 //
282 // Test Uninitialized access assert
283 //
284 template<class T>
285 void test_uninitialized_access( T const* )
286 {
287 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
288
289 optional<T> def ;
290
291 bool passed = false ;
292 try
293 {
294 // This should throw because 'def' is uninitialized
295 T const& n = def.get() ;
296 boost::ignore_unused(n);
297 passed = true ;
298 }
299 catch (...) {}
300 BOOST_TEST(!passed);
301
302 passed = false ;
303 try
304 {
305 // This should throw because 'def' is uninitialized
306 T const& n = *def ;
307 boost::ignore_unused(n);
308 passed = true ;
309 }
310 catch (...) {}
311 BOOST_TEST(!passed);
312
313 passed = false ;
314 try
315 {
316 T v(5) ;
317 boost::ignore_unused(v);
318 // This should throw because 'def' is uninitialized
319 *def = v ;
320 passed = true ;
321 }
322 catch (...) {}
323 BOOST_TEST(!passed);
324
325 passed = false ;
326 try
327 {
328 // This should throw because 'def' is uninitialized
329 T v = *(def.operator->()) ;
330 boost::ignore_unused(v);
331 passed = true ;
332 }
333 catch (...) {}
334 BOOST_TEST(!passed);
335 }
336
337 #if BOOST_WORKAROUND( BOOST_INTEL_CXX_VERSION, <= 700) // Intel C++ 7.0
338 void prevent_buggy_optimization( bool v ) {}
339 #endif
340
341 //
342 // Test Direct Initialization of optional for a T with throwing copy-ctor.
343 //
344 template<class T>
345 void test_throwing_direct_init( T const* )
346 {
347 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
348
349 T a(6);
350
351 int count = get_instance_count( ARG(T) ) ;
352
353 set_throw_on_copy( ARG(T) ) ;
354
355 bool passed = false ;
356 try
357 {
358 // This should:
359 // Attempt to copy construct 'a' and throw.
360 // 'opt' won't be constructed.
361 set_pending_copy( ARG(T) ) ;
362
363 #if BOOST_WORKAROUND( BOOST_INTEL_CXX_VERSION, <= 700) // Intel C++ 7.0
364 // Intel C++ 7.0 specific:
365 // For some reason, when "check_is_not_pending_copy",
366 // after the exception block is reached,
367 // X::pending_copy==true even though X's copy ctor set it to false.
368 // I guessed there is some sort of optimization bug,
369 // and it seems to be the since the following additional line just
370 // solves the problem (!?)
371 prevent_buggy_optimization(X::pending_copy);
372 #endif
373
374 optional<T> opt(a) ;
375 passed = true ;
376 }
377 catch ( ... ){}
378
379 BOOST_TEST(!passed);
380 check_is_not_pending_copy( ARG(T) );
381 check_instance_count(count, ARG(T) );
382
383 reset_throw_on_copy( ARG(T) ) ;
384
385 }
386
387 //
388 // Test Value Assignment to an Uninitialized optional for a T with a throwing copy-ctor
389 //
390 template<class T>
391 void test_throwing_val_assign_on_uninitialized( T const* )
392 {
393 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
394
395 T a(7);
396
397 int count = get_instance_count( ARG(T) ) ;
398
399 set_throw_on_copy( ARG(T) ) ;
400
401 optional<T> opt ;
402
403 bool passed = false ;
404 try
405 {
406 // This should:
407 // Attempt to copy construct 'a' and throw.
408 // opt should be left uninitialized.
409 set_pending_copy( ARG(T) ) ;
410 opt.reset( a );
411 passed = true ;
412 }
413 catch ( ... ) {}
414
415 BOOST_TEST(!passed);
416
417 check_is_not_pending_copy( ARG(T) );
418 check_instance_count(count, ARG(T) );
419 check_uninitialized(opt);
420
421 reset_throw_on_copy( ARG(T) ) ;
422 }
423
424 //
425 // Test Value Reset on an Initialized optional for a T with a throwing copy-ctor
426 //
427 template<class T>
428 void test_throwing_val_assign_on_initialized( T const* )
429 {
430 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
431
432 T z(0);
433 T a(8);
434 T b(9);
435 T x(-1);
436
437 int count = get_instance_count( ARG(T) ) ;
438
439 optional<T> opt ( b ) ;
440 ++ count ;
441
442 check_instance_count(count, ARG(T) );
443
444 check_value(opt,b,z);
445
446 set_throw_on_assign( ARG(T) ) ;
447
448 bool passed = false ;
449 try
450 {
451 // This should:
452 // Attempt to assign 'a' and throw.
453 // opt is kept initialized but its value not neccesarily fully assigned
454 // (in this test, incompletely assigned is flaged with the value -1 being set)
455 set_pending_assign( ARG(T) ) ;
456 opt.reset ( a ) ;
457 passed = true ;
458 }
459 catch ( ... ) {}
460
461 BOOST_TEST(!passed);
462
463 check_is_not_pending_assign( ARG(T) );
464 check_instance_count(count, ARG(T) );
465 check_initialized(opt);
466 check_value(opt,x,z);
467
468 reset_throw_on_assign ( ARG(T) ) ;
469 }
470
471 //
472 // Test Copy Initialization from an Initialized optional for a T with a throwing copy-ctor
473 //
474 template<class T>
475 void test_throwing_copy_initialization( T const* )
476 {
477 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
478
479 T z(0);
480 T a(10);
481
482 optional<T> opt (a);
483
484 int count = get_instance_count( ARG(T) ) ;
485
486 set_throw_on_copy( ARG(T) ) ;
487
488 bool passed = false ;
489 try
490 {
491 // This should:
492 // Attempt to copy construct 'opt' and throw.
493 // opt1 won't be constructed.
494 set_pending_copy( ARG(T) ) ;
495 optional<T> opt1 = opt ;
496 passed = true ;
497 }
498 catch ( ... ) {}
499
500 BOOST_TEST(!passed);
501
502 check_is_not_pending_copy( ARG(T) );
503 check_instance_count(count, ARG(T) );
504
505 // Nothing should have happened to the source optional.
506 check_initialized(opt);
507 check_value(opt,a,z);
508
509 reset_throw_on_copy( ARG(T) ) ;
510 }
511
512 //
513 // Test Assignment to an Uninitialized optional from an Initialized optional
514 // for a T with a throwing copy-ctor
515 //
516 template<class T>
517 void test_throwing_assign_to_uninitialized( T const* )
518 {
519 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
520
521 T z(0);
522 T a(11);
523
524 optional<T> opt0 ;
525 optional<T> opt1(a) ;
526
527 int count = get_instance_count( ARG(T) ) ;
528
529 set_throw_on_copy( ARG(T) ) ;
530
531 bool passed = false ;
532 try
533 {
534 // This should:
535 // Attempt to copy construct 'opt1.value()' into opt0 and throw.
536 // opt0 should be left uninitialized.
537 set_pending_copy( ARG(T) ) ;
538 opt0 = opt1 ;
539 passed = true ;
540 }
541 catch ( ... ) {}
542
543 BOOST_TEST(!passed);
544
545 check_is_not_pending_copy( ARG(T) );
546 check_instance_count(count, ARG(T) );
547 check_uninitialized(opt0);
548
549 reset_throw_on_copy( ARG(T) ) ;
550 }
551
552 //
553 // Test Assignment to an Initialized optional from an Initialized optional
554 // for a T with a throwing copy-ctor
555 //
556 template<class T>
557 void test_throwing_assign_to_initialized( T const* )
558 {
559 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
560
561 T z(0);
562 T a(12);
563 T b(13);
564 T x(-1);
565
566 optional<T> opt0(a) ;
567 optional<T> opt1(b) ;
568
569 int count = get_instance_count( ARG(T) ) ;
570
571 set_throw_on_assign( ARG(T) ) ;
572
573 bool passed = false ;
574 try
575 {
576 // This should:
577 // Attempt to copy construct 'opt1.value()' into opt0 and throw.
578 // opt0 is kept initialized but its value not neccesarily fully assigned
579 // (in this test, incompletely assigned is flaged with the value -1 being set)
580 set_pending_assign( ARG(T) ) ;
581 opt0 = opt1 ;
582 passed = true ;
583 }
584 catch ( ... ) {}
585
586 BOOST_TEST(!passed);
587
588 // opt0 was left uninitialized
589 check_is_not_pending_assign( ARG(T) );
590 check_instance_count(count, ARG(T) );
591 check_initialized(opt0);
592 check_value(opt0,x,z);
593
594 reset_throw_on_assign( ARG(T) ) ;
595 }
596
597 //
598 // Test swap in a no-throwing case
599 //
600 template<class T>
601 void test_no_throwing_swap( T const* )
602 {
603 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
604
605 T z(0);
606 T a(14);
607 T b(15);
608
609 optional<T> def0 ;
610 optional<T> def1 ;
611 optional<T> opt0(a) ;
612 optional<T> opt1(b) ;
613
614 int count = get_instance_count( ARG(T) ) ;
615
616 swap(def0,def1);
617 check_uninitialized(def0);
618 check_uninitialized(def1);
619
620 swap(def0,opt0);
621 check_uninitialized(opt0);
622 check_initialized(def0);
623 check_value(def0,a,z);
624
625 // restore def0 and opt0
626 swap(def0,opt0);
627
628 swap(opt0,opt1);
629 check_instance_count(count, ARG(T) );
630 check_initialized(opt0);
631 check_initialized(opt1);
632 check_value(opt0,b,z);
633 check_value(opt1,a,z);
634 }
635
636 //
637 // Test swap in a throwing case
638 //
639 template<class T>
640 void test_throwing_swap( T const* )
641 {
642 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
643
644 T a(16);
645 T b(17);
646 T x(-1);
647
648 optional<T> opt0(a) ;
649 optional<T> opt1(b) ;
650
651 set_throw_on_assign( ARG(T) ) ;
652
653 //
654 // Case 1: Both Initialized.
655 //
656 bool passed = false ;
657 try
658 {
659 // This should attempt to swap optionals and fail at swap(X&,X&).
660 swap(opt0,opt1);
661
662 passed = true ;
663 }
664 catch ( ... ) {}
665
666 BOOST_TEST(!passed);
667
668 // optional's swap doesn't affect the initialized states of the arguments. Therefore,
669 // the following must hold:
670 check_initialized(opt0);
671 check_initialized(opt1);
672 check_value(opt0,x,a);
673 check_value(opt1,b,x);
674
675
676 //
677 // Case 2: Only one Initialized.
678 //
679 reset_throw_on_assign( ARG(T) ) ;
680
681 opt0.reset();
682 opt1.reset(a);
683
684 set_throw_on_copy( ARG(T) ) ;
685
686 passed = false ;
687 try
688 {
689 // This should attempt to swap optionals and fail at opt0.reset(*opt1)
690 // Both opt0 and op1 are left unchanged (unswaped)
691 swap(opt0,opt1);
692
693 passed = true ;
694 }
695 catch ( ... ) {}
696
697 BOOST_TEST(!passed);
698
699 check_uninitialized(opt0);
700 check_initialized(opt1);
701 check_value(opt1,a,x);
702
703 reset_throw_on_copy( ARG(T) ) ;
704 }
705
706 //
707 // This verifies relational operators.
708 //
709 template<class T>
710 void test_relops( T const* )
711 {
712 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
713
714 T v0(0);
715 T v1(1);
716 T v2(1);
717
718 optional<T> def0 ;
719 optional<T> def1 ;
720 optional<T> opt0(v0);
721 optional<T> opt1(v1);
722 optional<T> opt2(v2);
723
724 // Check identity
725 BOOST_TEST ( def0 == def0 ) ;
726 BOOST_TEST ( opt0 == opt0 ) ;
727 BOOST_TEST ( !(def0 != def0) ) ;
728 BOOST_TEST ( !(opt0 != opt0) ) ;
729
730 // Check when both are uininitalized.
731 BOOST_TEST ( def0 == def1 ) ; // both uninitialized compare equal
732 BOOST_TEST ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized
733 BOOST_TEST ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized
734 BOOST_TEST ( !(def0 != def1) ) ;
735 BOOST_TEST ( def0 <= def1 ) ;
736 BOOST_TEST ( def0 >= def1 ) ;
737
738 // Check when only lhs is uninitialized.
739 BOOST_TEST ( def0 != opt0 ) ; // uninitialized is never equal to initialized
740 BOOST_TEST ( !(def0 == opt0) ) ;
741 BOOST_TEST ( def0 < opt0 ) ; // uninitialized is always less than initialized
742 BOOST_TEST ( !(def0 > opt0) ) ;
743 BOOST_TEST ( def0 <= opt0 ) ;
744 BOOST_TEST ( !(def0 >= opt0) ) ;
745
746 // Check when only rhs is uninitialized.
747 BOOST_TEST ( opt0 != def0 ) ; // initialized is never equal to uninitialized
748 BOOST_TEST ( !(opt0 == def0) ) ;
749 BOOST_TEST ( !(opt0 < def0) ) ; // initialized is never less than uninitialized
750 BOOST_TEST ( opt0 > def0 ) ;
751 BOOST_TEST ( !(opt0 <= def0) ) ;
752 BOOST_TEST ( opt0 >= opt0 ) ;
753
754 // If both are initialized, values are compared
755 BOOST_TEST ( opt0 != opt1 ) ;
756 BOOST_TEST ( opt1 == opt2 ) ;
757 BOOST_TEST ( opt0 < opt1 ) ;
758 BOOST_TEST ( opt1 > opt0 ) ;
759 BOOST_TEST ( opt1 <= opt2 ) ;
760 BOOST_TEST ( opt1 >= opt0 ) ;
761
762 // Compare against a value directly
763 BOOST_TEST ( opt0 == v0 ) ;
764 BOOST_TEST ( opt0 != v1 ) ;
765 BOOST_TEST ( opt1 == v2 ) ;
766 BOOST_TEST ( opt0 < v1 ) ;
767 BOOST_TEST ( opt1 > v0 ) ;
768 BOOST_TEST ( opt1 <= v2 ) ;
769 BOOST_TEST ( opt1 >= v0 ) ;
770 BOOST_TEST ( v0 != opt1 ) ;
771 BOOST_TEST ( v1 == opt2 ) ;
772 BOOST_TEST ( v0 < opt1 ) ;
773 BOOST_TEST ( v1 > opt0 ) ;
774 BOOST_TEST ( v1 <= opt2 ) ;
775 BOOST_TEST ( v1 >= opt0 ) ;
776 BOOST_TEST ( def0 != v0 ) ;
777 BOOST_TEST ( !(def0 == v0) ) ;
778 BOOST_TEST ( def0 < v0 ) ;
779 BOOST_TEST ( !(def0 > v0) ) ;
780 BOOST_TEST ( def0 <= v0 ) ;
781 BOOST_TEST ( !(def0 >= v0) ) ;
782 BOOST_TEST ( v0 != def0 ) ;
783 BOOST_TEST ( !(v0 == def0) ) ;
784 BOOST_TEST ( !(v0 < def0) ) ;
785 BOOST_TEST ( v0 > def0 ) ;
786 BOOST_TEST ( !(v0 <= def0) ) ;
787 BOOST_TEST ( v0 >= opt0 ) ;
788 }
789
790 template<class T>
791 void test_none( T const* )
792 {
793 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
794
795 using boost::none ;
796
797 optional<T> def0 ;
798 optional<T> def1(none) ;
799 optional<T> non_def( T(1234) ) ;
800
801 BOOST_TEST ( def0 == none ) ;
802 BOOST_TEST ( non_def != none ) ;
803 BOOST_TEST ( !def1 ) ;
804 BOOST_TEST ( !(non_def < none) ) ;
805 BOOST_TEST ( non_def > none ) ;
806 BOOST_TEST ( !(non_def <= none) ) ;
807 BOOST_TEST ( non_def >= none ) ;
808
809 non_def = none ;
810 BOOST_TEST ( !non_def ) ;
811
812 test_default_implicit_construction(T(1),none);
813 }
814
815 template<class T>
816 void test_arrow( T const* )
817 {
818 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
819
820 T a(1234);
821
822 optional<T> oa(a) ;
823 optional<T> const coa(a) ;
824
825 BOOST_TEST ( coa->V() == 1234 ) ;
826
827 oa->V() = 4321 ;
828
829 BOOST_TEST ( a.V() = 1234 ) ;
830 BOOST_TEST ( (*oa).V() = 4321 ) ;
831 }
832
833 void test_with_builtin_types()
834 {
835 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
836
837 test_basics( ARG(double) );
838 test_conditional_ctor_and_get_valur_or( ARG(double) );
839 test_uninitialized_access( ARG(double) );
840 test_no_throwing_swap( ARG(double) );
841 test_relops( ARG(double) ) ;
842 test_none( ARG(double) ) ;
843 }
844
845 // MSVC < 11.0 doesn't destroy X when we call ptr->VBase::VBase.
846 // Make sure that we work around this bug.
847 struct VBase : virtual X
848 {
849 VBase(int v) : X(v) {}
850 // MSVC 8.0 doesn't generate this correctly...
851 VBase(const VBase& other) : X(static_cast<const X&>(other)) {}
852 };
853
854 void test_with_class_type()
855 {
856 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
857
858 test_basics( ARG(X) );
859 test_basics( ARG(VBase) );
860 test_conditional_ctor_and_get_valur_or( ARG(X) );
861 test_direct_value_manip( ARG(X) );
862 test_uninitialized_access( ARG(X) );
863 test_throwing_direct_init( ARG(X) );
864 test_throwing_val_assign_on_uninitialized( ARG(X) );
865 test_throwing_val_assign_on_initialized( ARG(X) );
866 test_throwing_copy_initialization( ARG(X) );
867 test_throwing_assign_to_uninitialized( ARG(X) );
868 test_throwing_assign_to_initialized( ARG(X) );
869 test_no_throwing_swap( ARG(X) );
870 test_throwing_swap( ARG(X) );
871 test_relops( ARG(X) ) ;
872 test_none( ARG(X) ) ;
873 test_arrow( ARG(X) ) ;
874 BOOST_TEST ( X::count == 0 ) ;
875 }
876
877 int eat ( bool ) { return 1 ; }
878 int eat ( char ) { return 1 ; }
879 int eat ( int ) { return 1 ; }
880 int eat ( void const* ) { return 1 ; }
881
882 template<class T> int eat ( T ) { return 0 ; }
883
884 //
885 // This verifies that operator safe_bool() behaves properly.
886 //
887 template<class T>
888 void test_no_implicit_conversions_impl( T const& )
889 {
890 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
891
892 optional<T> def ;
893 BOOST_TEST ( eat(def) == 0 ) ;
894 }
895
896 void test_no_implicit_conversions()
897 {
898 TRACE( std::endl << BOOST_CURRENT_FUNCTION );
899
900 bool b = false ;
901 char c = 0 ;
902 int i = 0 ;
903 void const* p = 0 ;
904
905 test_no_implicit_conversions_impl(b);
906 test_no_implicit_conversions_impl(c);
907 test_no_implicit_conversions_impl(i);
908 test_no_implicit_conversions_impl(p);
909 }
910
911
912 // Test for support for classes with overridden operator&
913 class CustomAddressOfClass
914 {
915 int n;
916
917 public:
918 CustomAddressOfClass() : n(0) {}
919 CustomAddressOfClass(CustomAddressOfClass const& that) : n(that.n) {}
920 explicit CustomAddressOfClass(int m) : n(m) {}
921 int* operator& () { return &n; }
922 bool operator== (CustomAddressOfClass const& that) const { return n == that.n; }
923 };
924
925 void test_custom_addressof_operator()
926 {
927 boost::optional< CustomAddressOfClass > o1(CustomAddressOfClass(10));
928 BOOST_TEST(!!o1);
929 BOOST_TEST(o1.get() == CustomAddressOfClass(10));
930
931 o1 = CustomAddressOfClass(20);
932 BOOST_TEST(!!o1);
933 BOOST_TEST(o1.get() == CustomAddressOfClass(20));
934
935 o1 = boost::none;
936 BOOST_TEST(!o1);
937 }
938
939 int main()
940 {
941 try
942 {
943 test_with_class_type();
944 test_with_builtin_types();
945 test_no_implicit_conversions();
946 test_custom_addressof_operator();
947 }
948 catch ( ... )
949 {
950 BOOST_ERROR("Unexpected Exception caught!");
951 }
952
953 return boost::report_errors();
954 }