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