• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <boost/config.hpp>
2 
3 #if defined(BOOST_MSVC)
4 
5 #pragma warning(disable: 4786)  // identifier truncated in debug info
6 #pragma warning(disable: 4710)  // function not inlined
7 #pragma warning(disable: 4711)  // function selected for automatic inline expansion
8 #pragma warning(disable: 4514)  // unreferenced inline removed
9 #pragma warning(disable: 4355)  // 'this' : used in base member initializer list
10 #pragma warning(disable: 4511)  // copy constructor could not be generated
11 #pragma warning(disable: 4512)  // assignment operator could not be generated
12 
13 #if (BOOST_MSVC >= 1310)
14 #pragma warning(disable: 4675)  // resolved overload found with Koenig lookup
15 #endif
16 
17 #endif
18 
19 //
20 //  intrusive_ptr_test.cpp
21 //
22 //  Copyright (c) 2002-2005 Peter Dimov
23 //
24 // Distributed under the Boost Software License, Version 1.0. (See
25 // accompanying file LICENSE_1_0.txt or copy at
26 // http://www.boost.org/LICENSE_1_0.txt)
27 //
28 
29 #include <boost/core/lightweight_test.hpp>
30 #include <boost/intrusive_ptr.hpp>
31 #include <boost/detail/atomic_count.hpp>
32 #include <boost/config.hpp>
33 #include <algorithm>
34 #include <functional>
35 
36 //
37 
38 namespace N
39 {
40 
41 class base
42 {
43 private:
44 
45     mutable boost::detail::atomic_count use_count_;
46 
47     base(base const &);
48     base & operator=(base const &);
49 
50 protected:
51 
base()52     base(): use_count_(0)
53     {
54         ++instances;
55     }
56 
~base()57     virtual ~base()
58     {
59         --instances;
60     }
61 
62 public:
63 
64     static long instances;
65 
use_count() const66     long use_count() const
67     {
68         return use_count_;
69     }
70 
71 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
72 
intrusive_ptr_add_ref(base const * p)73     inline friend void intrusive_ptr_add_ref(base const * p)
74     {
75         ++p->use_count_;
76     }
77 
intrusive_ptr_release(base const * p)78     inline friend void intrusive_ptr_release(base const * p)
79     {
80         if(--p->use_count_ == 0) delete p;
81     }
82 
83 #else
84 
add_ref() const85     void add_ref() const
86     {
87         ++use_count_;
88     }
89 
release() const90     void release() const
91     {
92         if(--use_count_ == 0) delete this;
93     }
94 
95 #endif
96 };
97 
98 long base::instances = 0;
99 
100 } // namespace N
101 
102 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
103 
104 namespace boost
105 {
106 
intrusive_ptr_add_ref(N::base const * p)107 inline void intrusive_ptr_add_ref(N::base const * p)
108 {
109     p->add_ref();
110 }
111 
intrusive_ptr_release(N::base const * p)112 inline void intrusive_ptr_release(N::base const * p)
113 {
114     p->release();
115 }
116 
117 } // namespace boost
118 
119 #endif
120 
121 //
122 
123 struct X: public virtual N::base
124 {
125 };
126 
127 struct Y: public X
128 {
129 };
130 
131 //
132 
133 namespace n_element_type
134 {
135 
f(X &)136 void f(X &)
137 {
138 }
139 
test()140 void test()
141 {
142     typedef boost::intrusive_ptr<X>::element_type T;
143     T t;
144     f(t);
145 }
146 
147 } // namespace n_element_type
148 
149 namespace n_constructors
150 {
151 
default_constructor()152 void default_constructor()
153 {
154     boost::intrusive_ptr<X> px;
155     BOOST_TEST(px.get() == 0);
156 }
157 
pointer_constructor()158 void pointer_constructor()
159 {
160     {
161         boost::intrusive_ptr<X> px(0);
162         BOOST_TEST(px.get() == 0);
163     }
164 
165     {
166         boost::intrusive_ptr<X> px(0, false);
167         BOOST_TEST(px.get() == 0);
168     }
169 
170     BOOST_TEST( N::base::instances == 0 );
171 
172     {
173         X * p = new X;
174         BOOST_TEST(p->use_count() == 0);
175 
176         BOOST_TEST( N::base::instances == 1 );
177 
178         boost::intrusive_ptr<X> px(p);
179         BOOST_TEST(px.get() == p);
180         BOOST_TEST(px->use_count() == 1);
181     }
182 
183     BOOST_TEST( N::base::instances == 0 );
184 
185     {
186         X * p = new X;
187         BOOST_TEST(p->use_count() == 0);
188 
189         BOOST_TEST( N::base::instances == 1 );
190 
191 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
192         using boost::intrusive_ptr_add_ref;
193 #endif
194         intrusive_ptr_add_ref(p);
195         BOOST_TEST(p->use_count() == 1);
196 
197         boost::intrusive_ptr<X> px(p, false);
198         BOOST_TEST(px.get() == p);
199         BOOST_TEST(px->use_count() == 1);
200     }
201 
202     BOOST_TEST( N::base::instances == 0 );
203 }
204 
copy_constructor()205 void copy_constructor()
206 {
207     {
208         boost::intrusive_ptr<X> px;
209         boost::intrusive_ptr<X> px2(px);
210         BOOST_TEST(px2.get() == px.get());
211     }
212 
213     {
214         boost::intrusive_ptr<Y> py;
215         boost::intrusive_ptr<X> px(py);
216         BOOST_TEST(px.get() == py.get());
217     }
218 
219     {
220         boost::intrusive_ptr<X> px(0);
221         boost::intrusive_ptr<X> px2(px);
222         BOOST_TEST(px2.get() == px.get());
223     }
224 
225     {
226         boost::intrusive_ptr<Y> py(0);
227         boost::intrusive_ptr<X> px(py);
228         BOOST_TEST(px.get() == py.get());
229     }
230 
231     {
232         boost::intrusive_ptr<X> px(0, false);
233         boost::intrusive_ptr<X> px2(px);
234         BOOST_TEST(px2.get() == px.get());
235     }
236 
237     {
238         boost::intrusive_ptr<Y> py(0, false);
239         boost::intrusive_ptr<X> px(py);
240         BOOST_TEST(px.get() == py.get());
241     }
242 
243     BOOST_TEST( N::base::instances == 0 );
244 
245     {
246         boost::intrusive_ptr<X> px(new X);
247         boost::intrusive_ptr<X> px2(px);
248         BOOST_TEST( px2.get() == px.get() );
249 
250         BOOST_TEST( N::base::instances == 1 );
251     }
252 
253     BOOST_TEST( N::base::instances == 0 );
254 
255     {
256         boost::intrusive_ptr<Y> py(new Y);
257         boost::intrusive_ptr<X> px(py);
258         BOOST_TEST( px.get() == py.get() );
259 
260         BOOST_TEST( N::base::instances == 1 );
261     }
262 
263     BOOST_TEST( N::base::instances == 0 );
264 }
265 
test()266 void test()
267 {
268     default_constructor();
269     pointer_constructor();
270     copy_constructor();
271 }
272 
273 } // namespace n_constructors
274 
275 namespace n_destructor
276 {
277 
test()278 void test()
279 {
280     BOOST_TEST( N::base::instances == 0 );
281 
282     {
283         boost::intrusive_ptr<X> px(new X);
284         BOOST_TEST(px->use_count() == 1);
285 
286         BOOST_TEST( N::base::instances == 1 );
287 
288         {
289             boost::intrusive_ptr<X> px2(px);
290             BOOST_TEST(px->use_count() == 2);
291         }
292 
293         BOOST_TEST(px->use_count() == 1);
294     }
295 
296     BOOST_TEST( N::base::instances == 0 );
297 }
298 
299 } // namespace n_destructor
300 
301 namespace n_assignment
302 {
303 
copy_assignment()304 void copy_assignment()
305 {
306     BOOST_TEST( N::base::instances == 0 );
307 
308     {
309         boost::intrusive_ptr<X> p1;
310 
311         p1 = p1;
312 
313         BOOST_TEST(p1 == p1);
314         BOOST_TEST(p1? false: true);
315         BOOST_TEST(!p1);
316         BOOST_TEST(p1.get() == 0);
317 
318         boost::intrusive_ptr<X> p2;
319 
320         p1 = p2;
321 
322         BOOST_TEST(p1 == p2);
323         BOOST_TEST(p1? false: true);
324         BOOST_TEST(!p1);
325         BOOST_TEST(p1.get() == 0);
326 
327         boost::intrusive_ptr<X> p3(p1);
328 
329         p1 = p3;
330 
331         BOOST_TEST(p1 == p3);
332         BOOST_TEST(p1? false: true);
333         BOOST_TEST(!p1);
334         BOOST_TEST(p1.get() == 0);
335 
336         BOOST_TEST(N::base::instances == 0);
337 
338         boost::intrusive_ptr<X> p4(new X);
339 
340         BOOST_TEST(N::base::instances == 1);
341 
342         p1 = p4;
343 
344         BOOST_TEST(N::base::instances == 1);
345 
346         BOOST_TEST(p1 == p4);
347 
348         BOOST_TEST(p1->use_count() == 2);
349 
350         p1 = p2;
351 
352         BOOST_TEST(p1 == p2);
353         BOOST_TEST(N::base::instances == 1);
354 
355         p4 = p3;
356 
357         BOOST_TEST(p4 == p3);
358         BOOST_TEST(N::base::instances == 0);
359     }
360 }
361 
conversion_assignment()362 void conversion_assignment()
363 {
364     BOOST_TEST( N::base::instances == 0 );
365 
366     {
367         boost::intrusive_ptr<X> p1;
368 
369         boost::intrusive_ptr<Y> p2;
370 
371         p1 = p2;
372 
373         BOOST_TEST(p1 == p2);
374         BOOST_TEST(p1? false: true);
375         BOOST_TEST(!p1);
376         BOOST_TEST(p1.get() == 0);
377 
378         BOOST_TEST(N::base::instances == 0);
379 
380         boost::intrusive_ptr<Y> p4(new Y);
381 
382         BOOST_TEST(N::base::instances == 1);
383         BOOST_TEST(p4->use_count() == 1);
384 
385         boost::intrusive_ptr<X> p5(p4);
386         BOOST_TEST(p4->use_count() == 2);
387 
388         p1 = p4;
389 
390         BOOST_TEST(N::base::instances == 1);
391 
392         BOOST_TEST(p1 == p4);
393 
394         BOOST_TEST(p1->use_count() == 3);
395         BOOST_TEST(p4->use_count() == 3);
396 
397         p1 = p2;
398 
399         BOOST_TEST(p1 == p2);
400         BOOST_TEST(N::base::instances == 1);
401         BOOST_TEST(p4->use_count() == 2);
402 
403         p4 = p2;
404         p5 = p2;
405 
406         BOOST_TEST(p4 == p2);
407         BOOST_TEST(N::base::instances == 0);
408     }
409 }
410 
pointer_assignment()411 void pointer_assignment()
412 {
413     BOOST_TEST( N::base::instances == 0 );
414 
415     {
416         boost::intrusive_ptr<X> p1;
417 
418         p1 = p1.get();
419 
420         BOOST_TEST(p1 == p1);
421         BOOST_TEST(p1? false: true);
422         BOOST_TEST(!p1);
423         BOOST_TEST(p1.get() == 0);
424 
425         boost::intrusive_ptr<X> p2;
426 
427         p1 = p2.get();
428 
429         BOOST_TEST(p1 == p2);
430         BOOST_TEST(p1? false: true);
431         BOOST_TEST(!p1);
432         BOOST_TEST(p1.get() == 0);
433 
434         boost::intrusive_ptr<X> p3(p1);
435 
436         p1 = p3.get();
437 
438         BOOST_TEST(p1 == p3);
439         BOOST_TEST(p1? false: true);
440         BOOST_TEST(!p1);
441         BOOST_TEST(p1.get() == 0);
442 
443         BOOST_TEST(N::base::instances == 0);
444 
445         boost::intrusive_ptr<X> p4(new X);
446 
447         BOOST_TEST(N::base::instances == 1);
448 
449         p1 = p4.get();
450 
451         BOOST_TEST(N::base::instances == 1);
452 
453         BOOST_TEST(p1 == p4);
454 
455         BOOST_TEST(p1->use_count() == 2);
456 
457         p1 = p2.get();
458 
459         BOOST_TEST(p1 == p2);
460         BOOST_TEST(N::base::instances == 1);
461 
462         p4 = p3.get();
463 
464         BOOST_TEST(p4 == p3);
465         BOOST_TEST(N::base::instances == 0);
466     }
467 
468     {
469         boost::intrusive_ptr<X> p1;
470 
471         boost::intrusive_ptr<Y> p2;
472 
473         p1 = p2.get();
474 
475         BOOST_TEST(p1 == p2);
476         BOOST_TEST(p1? false: true);
477         BOOST_TEST(!p1);
478         BOOST_TEST(p1.get() == 0);
479 
480         BOOST_TEST(N::base::instances == 0);
481 
482         boost::intrusive_ptr<Y> p4(new Y);
483 
484         BOOST_TEST(N::base::instances == 1);
485         BOOST_TEST(p4->use_count() == 1);
486 
487         boost::intrusive_ptr<X> p5(p4);
488         BOOST_TEST(p4->use_count() == 2);
489 
490         p1 = p4.get();
491 
492         BOOST_TEST(N::base::instances == 1);
493 
494         BOOST_TEST(p1 == p4);
495 
496         BOOST_TEST(p1->use_count() == 3);
497         BOOST_TEST(p4->use_count() == 3);
498 
499         p1 = p2.get();
500 
501         BOOST_TEST(p1 == p2);
502         BOOST_TEST(N::base::instances == 1);
503         BOOST_TEST(p4->use_count() == 2);
504 
505         p4 = p2.get();
506         p5 = p2.get();
507 
508         BOOST_TEST(p4 == p2);
509         BOOST_TEST(N::base::instances == 0);
510     }
511 }
512 
test()513 void test()
514 {
515     copy_assignment();
516     conversion_assignment();
517     pointer_assignment();
518 }
519 
520 } // namespace n_assignment
521 
522 namespace n_reset
523 {
524 
test()525 void test()
526 {
527     BOOST_TEST( N::base::instances == 0 );
528 
529     {
530         boost::intrusive_ptr<X> px;
531         BOOST_TEST( px.get() == 0 );
532 
533         px.reset();
534         BOOST_TEST( px.get() == 0 );
535 
536         X * p = new X;
537         BOOST_TEST( p->use_count() == 0 );
538         BOOST_TEST( N::base::instances == 1 );
539 
540         px.reset( p );
541         BOOST_TEST( px.get() == p );
542         BOOST_TEST( px->use_count() == 1 );
543 
544         px.reset();
545         BOOST_TEST( px.get() == 0 );
546     }
547 
548     BOOST_TEST( N::base::instances == 0 );
549 
550     {
551         boost::intrusive_ptr<X> px( new X );
552         BOOST_TEST( N::base::instances == 1 );
553 
554         px.reset( 0 );
555         BOOST_TEST( px.get() == 0 );
556     }
557 
558     BOOST_TEST( N::base::instances == 0 );
559 
560     {
561         boost::intrusive_ptr<X> px( new X );
562         BOOST_TEST( N::base::instances == 1 );
563 
564         px.reset( 0, false );
565         BOOST_TEST( px.get() == 0 );
566     }
567 
568     BOOST_TEST( N::base::instances == 0 );
569 
570     {
571         boost::intrusive_ptr<X> px( new X );
572         BOOST_TEST( N::base::instances == 1 );
573 
574         px.reset( 0, true );
575         BOOST_TEST( px.get() == 0 );
576     }
577 
578     BOOST_TEST( N::base::instances == 0 );
579 
580     {
581         X * p = new X;
582         BOOST_TEST( p->use_count() == 0 );
583 
584         BOOST_TEST( N::base::instances == 1 );
585 
586         boost::intrusive_ptr<X> px;
587         BOOST_TEST( px.get() == 0 );
588 
589         px.reset( p, true );
590         BOOST_TEST( px.get() == p );
591         BOOST_TEST( px->use_count() == 1 );
592     }
593 
594     BOOST_TEST( N::base::instances == 0 );
595 
596     {
597         X * p = new X;
598         BOOST_TEST( p->use_count() == 0 );
599 
600         BOOST_TEST( N::base::instances == 1 );
601 
602 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
603         using boost::intrusive_ptr_add_ref;
604 #endif
605         intrusive_ptr_add_ref( p );
606         BOOST_TEST( p->use_count() == 1 );
607 
608         boost::intrusive_ptr<X> px;
609         BOOST_TEST( px.get() == 0 );
610 
611         px.reset( p, false );
612         BOOST_TEST( px.get() == p );
613         BOOST_TEST( px->use_count() == 1 );
614     }
615 
616     BOOST_TEST( N::base::instances == 0 );
617 
618     {
619         boost::intrusive_ptr<X> px( new X );
620         BOOST_TEST( px.get() != 0 );
621         BOOST_TEST( px->use_count() == 1 );
622 
623         BOOST_TEST( N::base::instances == 1 );
624 
625         X * p = new X;
626         BOOST_TEST( p->use_count() == 0 );
627 
628         BOOST_TEST( N::base::instances == 2 );
629 
630         px.reset( p );
631         BOOST_TEST( px.get() == p );
632         BOOST_TEST( px->use_count() == 1 );
633 
634         BOOST_TEST( N::base::instances == 1 );
635     }
636 
637     BOOST_TEST( N::base::instances == 0 );
638 
639     {
640         boost::intrusive_ptr<X> px( new X );
641         BOOST_TEST( px.get() != 0 );
642         BOOST_TEST( px->use_count() == 1 );
643 
644         BOOST_TEST( N::base::instances == 1 );
645 
646         X * p = new X;
647         BOOST_TEST( p->use_count() == 0 );
648 
649         BOOST_TEST( N::base::instances == 2 );
650 
651         px.reset( p, true );
652         BOOST_TEST( px.get() == p );
653         BOOST_TEST( px->use_count() == 1 );
654 
655         BOOST_TEST( N::base::instances == 1 );
656     }
657 
658     BOOST_TEST( N::base::instances == 0 );
659 
660     {
661         boost::intrusive_ptr<X> px( new X );
662         BOOST_TEST( px.get() != 0 );
663         BOOST_TEST( px->use_count() == 1 );
664 
665         BOOST_TEST( N::base::instances == 1 );
666 
667         X * p = new X;
668         BOOST_TEST( p->use_count() == 0 );
669 
670 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
671         using boost::intrusive_ptr_add_ref;
672 #endif
673         intrusive_ptr_add_ref( p );
674         BOOST_TEST( p->use_count() == 1 );
675 
676         BOOST_TEST( N::base::instances == 2 );
677 
678         px.reset( p, false );
679         BOOST_TEST( px.get() == p );
680         BOOST_TEST( px->use_count() == 1 );
681 
682         BOOST_TEST( N::base::instances == 1 );
683     }
684 
685     BOOST_TEST( N::base::instances == 0 );
686 }
687 
688 } // namespace n_reset
689 
690 namespace n_access
691 {
692 
test()693 void test()
694 {
695     {
696         boost::intrusive_ptr<X> px;
697         BOOST_TEST(px? false: true);
698         BOOST_TEST(!px);
699 
700 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
701         using boost::get_pointer;
702 #endif
703 
704         BOOST_TEST(get_pointer(px) == px.get());
705     }
706 
707     {
708         boost::intrusive_ptr<X> px(0);
709         BOOST_TEST(px? false: true);
710         BOOST_TEST(!px);
711 
712 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
713         using boost::get_pointer;
714 #endif
715 
716         BOOST_TEST(get_pointer(px) == px.get());
717     }
718 
719     {
720         boost::intrusive_ptr<X> px(new X);
721         BOOST_TEST(px? true: false);
722         BOOST_TEST(!!px);
723         BOOST_TEST(&*px == px.get());
724         BOOST_TEST(px.operator ->() == px.get());
725 
726 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
727         using boost::get_pointer;
728 #endif
729 
730         BOOST_TEST(get_pointer(px) == px.get());
731     }
732 
733     {
734         boost::intrusive_ptr<X> px;
735         X* detached = px.detach();
736         BOOST_TEST( px.get() == 0 );
737         BOOST_TEST( detached == 0 );
738     }
739 
740     {
741         X * p = new X;
742         BOOST_TEST( p->use_count() == 0 );
743 
744         boost::intrusive_ptr<X> px( p );
745         BOOST_TEST( px.get() == p );
746         BOOST_TEST( px->use_count() == 1 );
747 
748         X * detached = px.detach();
749         BOOST_TEST( px.get() == 0 );
750 
751         BOOST_TEST( detached == p );
752         BOOST_TEST( detached->use_count() == 1 );
753 
754         delete detached;
755     }
756 }
757 
758 } // namespace n_access
759 
760 namespace n_swap
761 {
762 
test()763 void test()
764 {
765     {
766         boost::intrusive_ptr<X> px;
767         boost::intrusive_ptr<X> px2;
768 
769         px.swap(px2);
770 
771         BOOST_TEST(px.get() == 0);
772         BOOST_TEST(px2.get() == 0);
773 
774         using std::swap;
775         swap(px, px2);
776 
777         BOOST_TEST(px.get() == 0);
778         BOOST_TEST(px2.get() == 0);
779     }
780 
781     {
782         X * p = new X;
783         boost::intrusive_ptr<X> px;
784         boost::intrusive_ptr<X> px2(p);
785         boost::intrusive_ptr<X> px3(px2);
786 
787         px.swap(px2);
788 
789         BOOST_TEST(px.get() == p);
790         BOOST_TEST(px->use_count() == 2);
791         BOOST_TEST(px2.get() == 0);
792         BOOST_TEST(px3.get() == p);
793         BOOST_TEST(px3->use_count() == 2);
794 
795         using std::swap;
796         swap(px, px2);
797 
798         BOOST_TEST(px.get() == 0);
799         BOOST_TEST(px2.get() == p);
800         BOOST_TEST(px2->use_count() == 2);
801         BOOST_TEST(px3.get() == p);
802         BOOST_TEST(px3->use_count() == 2);
803     }
804 
805     {
806         X * p1 = new X;
807         X * p2 = new X;
808         boost::intrusive_ptr<X> px(p1);
809         boost::intrusive_ptr<X> px2(p2);
810         boost::intrusive_ptr<X> px3(px2);
811 
812         px.swap(px2);
813 
814         BOOST_TEST(px.get() == p2);
815         BOOST_TEST(px->use_count() == 2);
816         BOOST_TEST(px2.get() == p1);
817         BOOST_TEST(px2->use_count() == 1);
818         BOOST_TEST(px3.get() == p2);
819         BOOST_TEST(px3->use_count() == 2);
820 
821         using std::swap;
822         swap(px, px2);
823 
824         BOOST_TEST(px.get() == p1);
825         BOOST_TEST(px->use_count() == 1);
826         BOOST_TEST(px2.get() == p2);
827         BOOST_TEST(px2->use_count() == 2);
828         BOOST_TEST(px3.get() == p2);
829         BOOST_TEST(px3->use_count() == 2);
830     }
831 }
832 
833 } // namespace n_swap
834 
835 namespace n_comparison
836 {
837 
test2(boost::intrusive_ptr<T> const & p,boost::intrusive_ptr<U> const & q)838 template<class T, class U> void test2(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<U> const & q)
839 {
840     BOOST_TEST((p == q) == (p.get() == q.get()));
841     BOOST_TEST((p != q) == (p.get() != q.get()));
842 }
843 
test3(boost::intrusive_ptr<T> const & p,boost::intrusive_ptr<T> const & q)844 template<class T> void test3(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<T> const & q)
845 {
846     BOOST_TEST((p == q) == (p.get() == q.get()));
847     BOOST_TEST((p.get() == q) == (p.get() == q.get()));
848     BOOST_TEST((p == q.get()) == (p.get() == q.get()));
849     BOOST_TEST((p != q) == (p.get() != q.get()));
850     BOOST_TEST((p.get() != q) == (p.get() != q.get()));
851     BOOST_TEST((p != q.get()) == (p.get() != q.get()));
852 
853     // 'less' moved here as a g++ 2.9x parse error workaround
854     std::less<T*> less;
855     BOOST_TEST((p < q) == less(p.get(), q.get()));
856 }
857 
test()858 void test()
859 {
860     {
861         boost::intrusive_ptr<X> px;
862         test3(px, px);
863 
864         boost::intrusive_ptr<X> px2;
865         test3(px, px2);
866 
867         boost::intrusive_ptr<X> px3(px);
868         test3(px3, px3);
869         test3(px, px3);
870     }
871 
872     {
873         boost::intrusive_ptr<X> px;
874 
875         boost::intrusive_ptr<X> px2(new X);
876         test3(px, px2);
877         test3(px2, px2);
878 
879         boost::intrusive_ptr<X> px3(new X);
880         test3(px2, px3);
881 
882         boost::intrusive_ptr<X> px4(px2);
883         test3(px2, px4);
884         test3(px4, px4);
885     }
886 
887     {
888         boost::intrusive_ptr<X> px(new X);
889 
890         boost::intrusive_ptr<Y> py(new Y);
891         test2(px, py);
892 
893         boost::intrusive_ptr<X> px2(py);
894         test2(px2, py);
895         test3(px, px2);
896         test3(px2, px2);
897     }
898 }
899 
900 } // namespace n_comparison
901 
902 namespace n_static_cast
903 {
904 
test()905 void test()
906 {
907     {
908         boost::intrusive_ptr<X> px(new Y);
909 
910         boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>(px);
911         BOOST_TEST(px.get() == py.get());
912         BOOST_TEST(px->use_count() == 2);
913         BOOST_TEST(py->use_count() == 2);
914 
915         boost::intrusive_ptr<X> px2(py);
916         BOOST_TEST(px2.get() == px.get());
917     }
918 
919     BOOST_TEST( N::base::instances == 0 );
920 
921     {
922         boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>( boost::intrusive_ptr<X>(new Y) );
923         BOOST_TEST(py.get() != 0);
924         BOOST_TEST(py->use_count() == 1);
925     }
926 
927     BOOST_TEST( N::base::instances == 0 );
928 }
929 
930 } // namespace n_static_cast
931 
932 namespace n_const_cast
933 {
934 
test()935 void test()
936 {
937     {
938         boost::intrusive_ptr<X const> px;
939 
940         boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>(px);
941         BOOST_TEST(px2.get() == 0);
942     }
943 
944     {
945         boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>( boost::intrusive_ptr<X const>() );
946         BOOST_TEST(px2.get() == 0);
947     }
948 
949     BOOST_TEST( N::base::instances == 0 );
950 
951     {
952         boost::intrusive_ptr<X const> px(new X);
953 
954         boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>(px);
955         BOOST_TEST(px2.get() == px.get());
956         BOOST_TEST(px2->use_count() == 2);
957         BOOST_TEST(px->use_count() == 2);
958     }
959 
960     BOOST_TEST( N::base::instances == 0 );
961 
962     {
963         boost::intrusive_ptr<X> px = boost::const_pointer_cast<X>( boost::intrusive_ptr<X const>(new X) );
964         BOOST_TEST(px.get() != 0);
965         BOOST_TEST(px->use_count() == 1);
966     }
967 
968     BOOST_TEST( N::base::instances == 0 );
969 }
970 
971 } // namespace n_const_cast
972 
973 namespace n_dynamic_cast
974 {
975 
test()976 void test()
977 {
978     {
979         boost::intrusive_ptr<X> px;
980 
981         boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
982         BOOST_TEST(py.get() == 0);
983     }
984 
985     {
986         boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>() );
987         BOOST_TEST(py.get() == 0);
988     }
989 
990     {
991         boost::intrusive_ptr<X> px(static_cast<X*>(0));
992 
993         boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
994         BOOST_TEST(py.get() == 0);
995     }
996 
997     {
998         boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(static_cast<X*>(0)) );
999         BOOST_TEST(py.get() == 0);
1000     }
1001 
1002     {
1003         boost::intrusive_ptr<X> px(new X);
1004 
1005         boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
1006         BOOST_TEST(py.get() == 0);
1007     }
1008 
1009     BOOST_TEST( N::base::instances == 0 );
1010 
1011     {
1012         boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(new X) );
1013         BOOST_TEST(py.get() == 0);
1014     }
1015 
1016     BOOST_TEST( N::base::instances == 0 );
1017 
1018     {
1019         boost::intrusive_ptr<X> px(new Y);
1020 
1021         boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
1022         BOOST_TEST(py.get() == px.get());
1023         BOOST_TEST(py->use_count() == 2);
1024         BOOST_TEST(px->use_count() == 2);
1025     }
1026 
1027     BOOST_TEST( N::base::instances == 0 );
1028 
1029     {
1030         boost::intrusive_ptr<X> px(new Y);
1031 
1032         boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(new Y) );
1033         BOOST_TEST(py.get() != 0);
1034         BOOST_TEST(py->use_count() == 1);
1035     }
1036 
1037     BOOST_TEST( N::base::instances == 0 );
1038 }
1039 
1040 } // namespace n_dynamic_cast
1041 
1042 namespace n_transitive
1043 {
1044 
1045 struct X: public N::base
1046 {
1047     boost::intrusive_ptr<X> next;
1048 };
1049 
test()1050 void test()
1051 {
1052     boost::intrusive_ptr<X> p(new X);
1053     p->next = boost::intrusive_ptr<X>(new X);
1054     BOOST_TEST(!p->next->next);
1055     p = p->next;
1056     BOOST_TEST(!p->next);
1057 }
1058 
1059 } // namespace n_transitive
1060 
1061 namespace n_report_1
1062 {
1063 
1064 class foo: public N::base
1065 {
1066 public:
1067 
foo()1068     foo(): m_self(this)
1069     {
1070     }
1071 
suicide()1072     void suicide()
1073     {
1074         m_self = 0;
1075     }
1076 
1077 private:
1078 
1079     boost::intrusive_ptr<foo> m_self;
1080 };
1081 
test()1082 void test()
1083 {
1084     foo * foo_ptr = new foo;
1085     foo_ptr->suicide();
1086 }
1087 
1088 } // namespace n_report_1
1089 
main()1090 int main()
1091 {
1092     n_element_type::test();
1093     n_constructors::test();
1094     n_destructor::test();
1095     n_assignment::test();
1096     n_reset::test();
1097     n_access::test();
1098     n_swap::test();
1099     n_comparison::test();
1100     n_static_cast::test();
1101     n_const_cast::test();
1102     n_dynamic_cast::test();
1103 
1104     n_transitive::test();
1105     n_report_1::test();
1106 
1107     return boost::report_errors();
1108 }
1109