intrusive_ptr_test.cpp 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  1. #include <boost/config.hpp>
  2. #if defined(BOOST_MSVC)
  3. #pragma warning(disable: 4786) // identifier truncated in debug info
  4. #pragma warning(disable: 4710) // function not inlined
  5. #pragma warning(disable: 4711) // function selected for automatic inline expansion
  6. #pragma warning(disable: 4514) // unreferenced inline removed
  7. #pragma warning(disable: 4355) // 'this' : used in base member initializer list
  8. #pragma warning(disable: 4511) // copy constructor could not be generated
  9. #pragma warning(disable: 4512) // assignment operator could not be generated
  10. #if (BOOST_MSVC >= 1310)
  11. #pragma warning(disable: 4675) // resolved overload found with Koenig lookup
  12. #endif
  13. #endif
  14. //
  15. // intrusive_ptr_test.cpp
  16. //
  17. // Copyright (c) 2002-2005 Peter Dimov
  18. //
  19. // Distributed under the Boost Software License, Version 1.0. (See
  20. // accompanying file LICENSE_1_0.txt or copy at
  21. // http://www.boost.org/LICENSE_1_0.txt)
  22. //
  23. #include <boost/detail/lightweight_test.hpp>
  24. #include <boost/intrusive_ptr.hpp>
  25. #include <boost/detail/atomic_count.hpp>
  26. #include <boost/config.hpp>
  27. #include <algorithm>
  28. #include <functional>
  29. //
  30. namespace N
  31. {
  32. class base
  33. {
  34. private:
  35. mutable boost::detail::atomic_count use_count_;
  36. base(base const &);
  37. base & operator=(base const &);
  38. protected:
  39. base(): use_count_(0)
  40. {
  41. ++instances;
  42. }
  43. virtual ~base()
  44. {
  45. --instances;
  46. }
  47. public:
  48. static long instances;
  49. long use_count() const
  50. {
  51. return use_count_;
  52. }
  53. #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  54. inline friend void intrusive_ptr_add_ref(base const * p)
  55. {
  56. ++p->use_count_;
  57. }
  58. inline friend void intrusive_ptr_release(base const * p)
  59. {
  60. if(--p->use_count_ == 0) delete p;
  61. }
  62. #else
  63. void add_ref() const
  64. {
  65. ++use_count_;
  66. }
  67. void release() const
  68. {
  69. if(--use_count_ == 0) delete this;
  70. }
  71. #endif
  72. };
  73. long base::instances = 0;
  74. } // namespace N
  75. #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  76. namespace boost
  77. {
  78. inline void intrusive_ptr_add_ref(N::base const * p)
  79. {
  80. p->add_ref();
  81. }
  82. inline void intrusive_ptr_release(N::base const * p)
  83. {
  84. p->release();
  85. }
  86. } // namespace boost
  87. #endif
  88. //
  89. struct X: public virtual N::base
  90. {
  91. };
  92. struct Y: public X
  93. {
  94. };
  95. //
  96. namespace n_element_type
  97. {
  98. void f(X &)
  99. {
  100. }
  101. void test()
  102. {
  103. typedef boost::intrusive_ptr<X>::element_type T;
  104. T t;
  105. f(t);
  106. }
  107. } // namespace n_element_type
  108. namespace n_constructors
  109. {
  110. void default_constructor()
  111. {
  112. boost::intrusive_ptr<X> px;
  113. BOOST_TEST(px.get() == 0);
  114. }
  115. void pointer_constructor()
  116. {
  117. {
  118. boost::intrusive_ptr<X> px(0);
  119. BOOST_TEST(px.get() == 0);
  120. }
  121. {
  122. boost::intrusive_ptr<X> px(0, false);
  123. BOOST_TEST(px.get() == 0);
  124. }
  125. BOOST_TEST( N::base::instances == 0 );
  126. {
  127. X * p = new X;
  128. BOOST_TEST(p->use_count() == 0);
  129. BOOST_TEST( N::base::instances == 1 );
  130. boost::intrusive_ptr<X> px(p);
  131. BOOST_TEST(px.get() == p);
  132. BOOST_TEST(px->use_count() == 1);
  133. }
  134. BOOST_TEST( N::base::instances == 0 );
  135. {
  136. X * p = new X;
  137. BOOST_TEST(p->use_count() == 0);
  138. BOOST_TEST( N::base::instances == 1 );
  139. #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  140. using boost::intrusive_ptr_add_ref;
  141. #endif
  142. intrusive_ptr_add_ref(p);
  143. BOOST_TEST(p->use_count() == 1);
  144. boost::intrusive_ptr<X> px(p, false);
  145. BOOST_TEST(px.get() == p);
  146. BOOST_TEST(px->use_count() == 1);
  147. }
  148. BOOST_TEST( N::base::instances == 0 );
  149. }
  150. void copy_constructor()
  151. {
  152. {
  153. boost::intrusive_ptr<X> px;
  154. boost::intrusive_ptr<X> px2(px);
  155. BOOST_TEST(px2.get() == px.get());
  156. }
  157. {
  158. boost::intrusive_ptr<Y> py;
  159. boost::intrusive_ptr<X> px(py);
  160. BOOST_TEST(px.get() == py.get());
  161. }
  162. {
  163. boost::intrusive_ptr<X> px(0);
  164. boost::intrusive_ptr<X> px2(px);
  165. BOOST_TEST(px2.get() == px.get());
  166. }
  167. {
  168. boost::intrusive_ptr<Y> py(0);
  169. boost::intrusive_ptr<X> px(py);
  170. BOOST_TEST(px.get() == py.get());
  171. }
  172. {
  173. boost::intrusive_ptr<X> px(0, false);
  174. boost::intrusive_ptr<X> px2(px);
  175. BOOST_TEST(px2.get() == px.get());
  176. }
  177. {
  178. boost::intrusive_ptr<Y> py(0, false);
  179. boost::intrusive_ptr<X> px(py);
  180. BOOST_TEST(px.get() == py.get());
  181. }
  182. BOOST_TEST( N::base::instances == 0 );
  183. {
  184. boost::intrusive_ptr<X> px(new X);
  185. boost::intrusive_ptr<X> px2(px);
  186. BOOST_TEST( px2.get() == px.get() );
  187. BOOST_TEST( N::base::instances == 1 );
  188. }
  189. BOOST_TEST( N::base::instances == 0 );
  190. {
  191. boost::intrusive_ptr<Y> py(new Y);
  192. boost::intrusive_ptr<X> px(py);
  193. BOOST_TEST( px.get() == py.get() );
  194. BOOST_TEST( N::base::instances == 1 );
  195. }
  196. BOOST_TEST( N::base::instances == 0 );
  197. }
  198. void test()
  199. {
  200. default_constructor();
  201. pointer_constructor();
  202. copy_constructor();
  203. }
  204. } // namespace n_constructors
  205. namespace n_destructor
  206. {
  207. void test()
  208. {
  209. BOOST_TEST( N::base::instances == 0 );
  210. {
  211. boost::intrusive_ptr<X> px(new X);
  212. BOOST_TEST(px->use_count() == 1);
  213. BOOST_TEST( N::base::instances == 1 );
  214. {
  215. boost::intrusive_ptr<X> px2(px);
  216. BOOST_TEST(px->use_count() == 2);
  217. }
  218. BOOST_TEST(px->use_count() == 1);
  219. }
  220. BOOST_TEST( N::base::instances == 0 );
  221. }
  222. } // namespace n_destructor
  223. namespace n_assignment
  224. {
  225. void copy_assignment()
  226. {
  227. BOOST_TEST( N::base::instances == 0 );
  228. {
  229. boost::intrusive_ptr<X> p1;
  230. p1 = p1;
  231. BOOST_TEST(p1 == p1);
  232. BOOST_TEST(p1? false: true);
  233. BOOST_TEST(!p1);
  234. BOOST_TEST(p1.get() == 0);
  235. boost::intrusive_ptr<X> p2;
  236. p1 = p2;
  237. BOOST_TEST(p1 == p2);
  238. BOOST_TEST(p1? false: true);
  239. BOOST_TEST(!p1);
  240. BOOST_TEST(p1.get() == 0);
  241. boost::intrusive_ptr<X> p3(p1);
  242. p1 = p3;
  243. BOOST_TEST(p1 == p3);
  244. BOOST_TEST(p1? false: true);
  245. BOOST_TEST(!p1);
  246. BOOST_TEST(p1.get() == 0);
  247. BOOST_TEST(N::base::instances == 0);
  248. boost::intrusive_ptr<X> p4(new X);
  249. BOOST_TEST(N::base::instances == 1);
  250. p1 = p4;
  251. BOOST_TEST(N::base::instances == 1);
  252. BOOST_TEST(p1 == p4);
  253. BOOST_TEST(p1->use_count() == 2);
  254. p1 = p2;
  255. BOOST_TEST(p1 == p2);
  256. BOOST_TEST(N::base::instances == 1);
  257. p4 = p3;
  258. BOOST_TEST(p4 == p3);
  259. BOOST_TEST(N::base::instances == 0);
  260. }
  261. }
  262. void conversion_assignment()
  263. {
  264. BOOST_TEST( N::base::instances == 0 );
  265. {
  266. boost::intrusive_ptr<X> p1;
  267. boost::intrusive_ptr<Y> p2;
  268. p1 = p2;
  269. BOOST_TEST(p1 == p2);
  270. BOOST_TEST(p1? false: true);
  271. BOOST_TEST(!p1);
  272. BOOST_TEST(p1.get() == 0);
  273. BOOST_TEST(N::base::instances == 0);
  274. boost::intrusive_ptr<Y> p4(new Y);
  275. BOOST_TEST(N::base::instances == 1);
  276. BOOST_TEST(p4->use_count() == 1);
  277. boost::intrusive_ptr<X> p5(p4);
  278. BOOST_TEST(p4->use_count() == 2);
  279. p1 = p4;
  280. BOOST_TEST(N::base::instances == 1);
  281. BOOST_TEST(p1 == p4);
  282. BOOST_TEST(p1->use_count() == 3);
  283. BOOST_TEST(p4->use_count() == 3);
  284. p1 = p2;
  285. BOOST_TEST(p1 == p2);
  286. BOOST_TEST(N::base::instances == 1);
  287. BOOST_TEST(p4->use_count() == 2);
  288. p4 = p2;
  289. p5 = p2;
  290. BOOST_TEST(p4 == p2);
  291. BOOST_TEST(N::base::instances == 0);
  292. }
  293. }
  294. void pointer_assignment()
  295. {
  296. BOOST_TEST( N::base::instances == 0 );
  297. {
  298. boost::intrusive_ptr<X> p1;
  299. p1 = p1.get();
  300. BOOST_TEST(p1 == p1);
  301. BOOST_TEST(p1? false: true);
  302. BOOST_TEST(!p1);
  303. BOOST_TEST(p1.get() == 0);
  304. boost::intrusive_ptr<X> p2;
  305. p1 = p2.get();
  306. BOOST_TEST(p1 == p2);
  307. BOOST_TEST(p1? false: true);
  308. BOOST_TEST(!p1);
  309. BOOST_TEST(p1.get() == 0);
  310. boost::intrusive_ptr<X> p3(p1);
  311. p1 = p3.get();
  312. BOOST_TEST(p1 == p3);
  313. BOOST_TEST(p1? false: true);
  314. BOOST_TEST(!p1);
  315. BOOST_TEST(p1.get() == 0);
  316. BOOST_TEST(N::base::instances == 0);
  317. boost::intrusive_ptr<X> p4(new X);
  318. BOOST_TEST(N::base::instances == 1);
  319. p1 = p4.get();
  320. BOOST_TEST(N::base::instances == 1);
  321. BOOST_TEST(p1 == p4);
  322. BOOST_TEST(p1->use_count() == 2);
  323. p1 = p2.get();
  324. BOOST_TEST(p1 == p2);
  325. BOOST_TEST(N::base::instances == 1);
  326. p4 = p3.get();
  327. BOOST_TEST(p4 == p3);
  328. BOOST_TEST(N::base::instances == 0);
  329. }
  330. {
  331. boost::intrusive_ptr<X> p1;
  332. boost::intrusive_ptr<Y> p2;
  333. p1 = p2.get();
  334. BOOST_TEST(p1 == p2);
  335. BOOST_TEST(p1? false: true);
  336. BOOST_TEST(!p1);
  337. BOOST_TEST(p1.get() == 0);
  338. BOOST_TEST(N::base::instances == 0);
  339. boost::intrusive_ptr<Y> p4(new Y);
  340. BOOST_TEST(N::base::instances == 1);
  341. BOOST_TEST(p4->use_count() == 1);
  342. boost::intrusive_ptr<X> p5(p4);
  343. BOOST_TEST(p4->use_count() == 2);
  344. p1 = p4.get();
  345. BOOST_TEST(N::base::instances == 1);
  346. BOOST_TEST(p1 == p4);
  347. BOOST_TEST(p1->use_count() == 3);
  348. BOOST_TEST(p4->use_count() == 3);
  349. p1 = p2.get();
  350. BOOST_TEST(p1 == p2);
  351. BOOST_TEST(N::base::instances == 1);
  352. BOOST_TEST(p4->use_count() == 2);
  353. p4 = p2.get();
  354. p5 = p2.get();
  355. BOOST_TEST(p4 == p2);
  356. BOOST_TEST(N::base::instances == 0);
  357. }
  358. }
  359. void test()
  360. {
  361. copy_assignment();
  362. conversion_assignment();
  363. pointer_assignment();
  364. }
  365. } // namespace n_assignment
  366. namespace n_reset
  367. {
  368. void test()
  369. {
  370. BOOST_TEST( N::base::instances == 0 );
  371. {
  372. boost::intrusive_ptr<X> px;
  373. BOOST_TEST( px.get() == 0 );
  374. px.reset();
  375. BOOST_TEST( px.get() == 0 );
  376. X * p = new X;
  377. BOOST_TEST( p->use_count() == 0 );
  378. BOOST_TEST( N::base::instances == 1 );
  379. px.reset( p );
  380. BOOST_TEST( px.get() == p );
  381. BOOST_TEST( px->use_count() == 1 );
  382. px.reset();
  383. BOOST_TEST( px.get() == 0 );
  384. }
  385. BOOST_TEST( N::base::instances == 0 );
  386. {
  387. boost::intrusive_ptr<X> px( new X );
  388. BOOST_TEST( N::base::instances == 1 );
  389. px.reset( 0 );
  390. BOOST_TEST( px.get() == 0 );
  391. }
  392. BOOST_TEST( N::base::instances == 0 );
  393. {
  394. boost::intrusive_ptr<X> px( new X );
  395. BOOST_TEST( N::base::instances == 1 );
  396. px.reset( 0, false );
  397. BOOST_TEST( px.get() == 0 );
  398. }
  399. BOOST_TEST( N::base::instances == 0 );
  400. {
  401. boost::intrusive_ptr<X> px( new X );
  402. BOOST_TEST( N::base::instances == 1 );
  403. px.reset( 0, true );
  404. BOOST_TEST( px.get() == 0 );
  405. }
  406. BOOST_TEST( N::base::instances == 0 );
  407. {
  408. X * p = new X;
  409. BOOST_TEST( p->use_count() == 0 );
  410. BOOST_TEST( N::base::instances == 1 );
  411. boost::intrusive_ptr<X> px;
  412. BOOST_TEST( px.get() == 0 );
  413. px.reset( p, true );
  414. BOOST_TEST( px.get() == p );
  415. BOOST_TEST( px->use_count() == 1 );
  416. }
  417. BOOST_TEST( N::base::instances == 0 );
  418. {
  419. X * p = new X;
  420. BOOST_TEST( p->use_count() == 0 );
  421. BOOST_TEST( N::base::instances == 1 );
  422. #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  423. using boost::intrusive_ptr_add_ref;
  424. #endif
  425. intrusive_ptr_add_ref( p );
  426. BOOST_TEST( p->use_count() == 1 );
  427. boost::intrusive_ptr<X> px;
  428. BOOST_TEST( px.get() == 0 );
  429. px.reset( p, false );
  430. BOOST_TEST( px.get() == p );
  431. BOOST_TEST( px->use_count() == 1 );
  432. }
  433. BOOST_TEST( N::base::instances == 0 );
  434. {
  435. boost::intrusive_ptr<X> px( new X );
  436. BOOST_TEST( px.get() != 0 );
  437. BOOST_TEST( px->use_count() == 1 );
  438. BOOST_TEST( N::base::instances == 1 );
  439. X * p = new X;
  440. BOOST_TEST( p->use_count() == 0 );
  441. BOOST_TEST( N::base::instances == 2 );
  442. px.reset( p );
  443. BOOST_TEST( px.get() == p );
  444. BOOST_TEST( px->use_count() == 1 );
  445. BOOST_TEST( N::base::instances == 1 );
  446. }
  447. BOOST_TEST( N::base::instances == 0 );
  448. {
  449. boost::intrusive_ptr<X> px( new X );
  450. BOOST_TEST( px.get() != 0 );
  451. BOOST_TEST( px->use_count() == 1 );
  452. BOOST_TEST( N::base::instances == 1 );
  453. X * p = new X;
  454. BOOST_TEST( p->use_count() == 0 );
  455. BOOST_TEST( N::base::instances == 2 );
  456. px.reset( p, true );
  457. BOOST_TEST( px.get() == p );
  458. BOOST_TEST( px->use_count() == 1 );
  459. BOOST_TEST( N::base::instances == 1 );
  460. }
  461. BOOST_TEST( N::base::instances == 0 );
  462. {
  463. boost::intrusive_ptr<X> px( new X );
  464. BOOST_TEST( px.get() != 0 );
  465. BOOST_TEST( px->use_count() == 1 );
  466. BOOST_TEST( N::base::instances == 1 );
  467. X * p = new X;
  468. BOOST_TEST( p->use_count() == 0 );
  469. #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  470. using boost::intrusive_ptr_add_ref;
  471. #endif
  472. intrusive_ptr_add_ref( p );
  473. BOOST_TEST( p->use_count() == 1 );
  474. BOOST_TEST( N::base::instances == 2 );
  475. px.reset( p, false );
  476. BOOST_TEST( px.get() == p );
  477. BOOST_TEST( px->use_count() == 1 );
  478. BOOST_TEST( N::base::instances == 1 );
  479. }
  480. BOOST_TEST( N::base::instances == 0 );
  481. }
  482. } // namespace n_reset
  483. namespace n_access
  484. {
  485. void test()
  486. {
  487. {
  488. boost::intrusive_ptr<X> px;
  489. BOOST_TEST(px? false: true);
  490. BOOST_TEST(!px);
  491. #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  492. using boost::get_pointer;
  493. #endif
  494. BOOST_TEST(get_pointer(px) == px.get());
  495. }
  496. {
  497. boost::intrusive_ptr<X> px(0);
  498. BOOST_TEST(px? false: true);
  499. BOOST_TEST(!px);
  500. #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  501. using boost::get_pointer;
  502. #endif
  503. BOOST_TEST(get_pointer(px) == px.get());
  504. }
  505. {
  506. boost::intrusive_ptr<X> px(new X);
  507. BOOST_TEST(px? true: false);
  508. BOOST_TEST(!!px);
  509. BOOST_TEST(&*px == px.get());
  510. BOOST_TEST(px.operator ->() == px.get());
  511. #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  512. using boost::get_pointer;
  513. #endif
  514. BOOST_TEST(get_pointer(px) == px.get());
  515. }
  516. {
  517. boost::intrusive_ptr<X> px;
  518. X* detached = px.detach();
  519. BOOST_TEST( px.get() == 0 );
  520. BOOST_TEST( detached == 0 );
  521. }
  522. {
  523. X * p = new X;
  524. BOOST_TEST( p->use_count() == 0 );
  525. boost::intrusive_ptr<X> px( p );
  526. BOOST_TEST( px.get() == p );
  527. BOOST_TEST( px->use_count() == 1 );
  528. X * detached = px.detach();
  529. BOOST_TEST( px.get() == 0 );
  530. BOOST_TEST( detached == p );
  531. BOOST_TEST( detached->use_count() == 1 );
  532. delete detached;
  533. }
  534. }
  535. } // namespace n_access
  536. namespace n_swap
  537. {
  538. void test()
  539. {
  540. {
  541. boost::intrusive_ptr<X> px;
  542. boost::intrusive_ptr<X> px2;
  543. px.swap(px2);
  544. BOOST_TEST(px.get() == 0);
  545. BOOST_TEST(px2.get() == 0);
  546. using std::swap;
  547. swap(px, px2);
  548. BOOST_TEST(px.get() == 0);
  549. BOOST_TEST(px2.get() == 0);
  550. }
  551. {
  552. X * p = new X;
  553. boost::intrusive_ptr<X> px;
  554. boost::intrusive_ptr<X> px2(p);
  555. boost::intrusive_ptr<X> px3(px2);
  556. px.swap(px2);
  557. BOOST_TEST(px.get() == p);
  558. BOOST_TEST(px->use_count() == 2);
  559. BOOST_TEST(px2.get() == 0);
  560. BOOST_TEST(px3.get() == p);
  561. BOOST_TEST(px3->use_count() == 2);
  562. using std::swap;
  563. swap(px, px2);
  564. BOOST_TEST(px.get() == 0);
  565. BOOST_TEST(px2.get() == p);
  566. BOOST_TEST(px2->use_count() == 2);
  567. BOOST_TEST(px3.get() == p);
  568. BOOST_TEST(px3->use_count() == 2);
  569. }
  570. {
  571. X * p1 = new X;
  572. X * p2 = new X;
  573. boost::intrusive_ptr<X> px(p1);
  574. boost::intrusive_ptr<X> px2(p2);
  575. boost::intrusive_ptr<X> px3(px2);
  576. px.swap(px2);
  577. BOOST_TEST(px.get() == p2);
  578. BOOST_TEST(px->use_count() == 2);
  579. BOOST_TEST(px2.get() == p1);
  580. BOOST_TEST(px2->use_count() == 1);
  581. BOOST_TEST(px3.get() == p2);
  582. BOOST_TEST(px3->use_count() == 2);
  583. using std::swap;
  584. swap(px, px2);
  585. BOOST_TEST(px.get() == p1);
  586. BOOST_TEST(px->use_count() == 1);
  587. BOOST_TEST(px2.get() == p2);
  588. BOOST_TEST(px2->use_count() == 2);
  589. BOOST_TEST(px3.get() == p2);
  590. BOOST_TEST(px3->use_count() == 2);
  591. }
  592. }
  593. } // namespace n_swap
  594. namespace n_comparison
  595. {
  596. template<class T, class U> void test2(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<U> const & q)
  597. {
  598. BOOST_TEST((p == q) == (p.get() == q.get()));
  599. BOOST_TEST((p != q) == (p.get() != q.get()));
  600. }
  601. template<class T> void test3(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<T> const & q)
  602. {
  603. BOOST_TEST((p == q) == (p.get() == q.get()));
  604. BOOST_TEST((p.get() == q) == (p.get() == q.get()));
  605. BOOST_TEST((p == q.get()) == (p.get() == q.get()));
  606. BOOST_TEST((p != q) == (p.get() != q.get()));
  607. BOOST_TEST((p.get() != q) == (p.get() != q.get()));
  608. BOOST_TEST((p != q.get()) == (p.get() != q.get()));
  609. // 'less' moved here as a g++ 2.9x parse error workaround
  610. std::less<T*> less;
  611. BOOST_TEST((p < q) == less(p.get(), q.get()));
  612. }
  613. void test()
  614. {
  615. {
  616. boost::intrusive_ptr<X> px;
  617. test3(px, px);
  618. boost::intrusive_ptr<X> px2;
  619. test3(px, px2);
  620. boost::intrusive_ptr<X> px3(px);
  621. test3(px3, px3);
  622. test3(px, px3);
  623. }
  624. {
  625. boost::intrusive_ptr<X> px;
  626. boost::intrusive_ptr<X> px2(new X);
  627. test3(px, px2);
  628. test3(px2, px2);
  629. boost::intrusive_ptr<X> px3(new X);
  630. test3(px2, px3);
  631. boost::intrusive_ptr<X> px4(px2);
  632. test3(px2, px4);
  633. test3(px4, px4);
  634. }
  635. {
  636. boost::intrusive_ptr<X> px(new X);
  637. boost::intrusive_ptr<Y> py(new Y);
  638. test2(px, py);
  639. boost::intrusive_ptr<X> px2(py);
  640. test2(px2, py);
  641. test3(px, px2);
  642. test3(px2, px2);
  643. }
  644. }
  645. } // namespace n_comparison
  646. namespace n_static_cast
  647. {
  648. void test()
  649. {
  650. {
  651. boost::intrusive_ptr<X> px(new Y);
  652. boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>(px);
  653. BOOST_TEST(px.get() == py.get());
  654. BOOST_TEST(px->use_count() == 2);
  655. BOOST_TEST(py->use_count() == 2);
  656. boost::intrusive_ptr<X> px2(py);
  657. BOOST_TEST(px2.get() == px.get());
  658. }
  659. BOOST_TEST( N::base::instances == 0 );
  660. {
  661. boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>( boost::intrusive_ptr<X>(new Y) );
  662. BOOST_TEST(py.get() != 0);
  663. BOOST_TEST(py->use_count() == 1);
  664. }
  665. BOOST_TEST( N::base::instances == 0 );
  666. }
  667. } // namespace n_static_cast
  668. namespace n_const_cast
  669. {
  670. void test()
  671. {
  672. {
  673. boost::intrusive_ptr<X const> px;
  674. boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>(px);
  675. BOOST_TEST(px2.get() == 0);
  676. }
  677. {
  678. boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>( boost::intrusive_ptr<X const>() );
  679. BOOST_TEST(px2.get() == 0);
  680. }
  681. BOOST_TEST( N::base::instances == 0 );
  682. {
  683. boost::intrusive_ptr<X const> px(new X);
  684. boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>(px);
  685. BOOST_TEST(px2.get() == px.get());
  686. BOOST_TEST(px2->use_count() == 2);
  687. BOOST_TEST(px->use_count() == 2);
  688. }
  689. BOOST_TEST( N::base::instances == 0 );
  690. {
  691. boost::intrusive_ptr<X> px = boost::const_pointer_cast<X>( boost::intrusive_ptr<X const>(new X) );
  692. BOOST_TEST(px.get() != 0);
  693. BOOST_TEST(px->use_count() == 1);
  694. }
  695. BOOST_TEST( N::base::instances == 0 );
  696. }
  697. } // namespace n_const_cast
  698. namespace n_dynamic_cast
  699. {
  700. void test()
  701. {
  702. {
  703. boost::intrusive_ptr<X> px;
  704. boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
  705. BOOST_TEST(py.get() == 0);
  706. }
  707. {
  708. boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>() );
  709. BOOST_TEST(py.get() == 0);
  710. }
  711. {
  712. boost::intrusive_ptr<X> px(static_cast<X*>(0));
  713. boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
  714. BOOST_TEST(py.get() == 0);
  715. }
  716. {
  717. boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(static_cast<X*>(0)) );
  718. BOOST_TEST(py.get() == 0);
  719. }
  720. {
  721. boost::intrusive_ptr<X> px(new X);
  722. boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
  723. BOOST_TEST(py.get() == 0);
  724. }
  725. BOOST_TEST( N::base::instances == 0 );
  726. {
  727. boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(new X) );
  728. BOOST_TEST(py.get() == 0);
  729. }
  730. BOOST_TEST( N::base::instances == 0 );
  731. {
  732. boost::intrusive_ptr<X> px(new Y);
  733. boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
  734. BOOST_TEST(py.get() == px.get());
  735. BOOST_TEST(py->use_count() == 2);
  736. BOOST_TEST(px->use_count() == 2);
  737. }
  738. BOOST_TEST( N::base::instances == 0 );
  739. {
  740. boost::intrusive_ptr<X> px(new Y);
  741. boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(new Y) );
  742. BOOST_TEST(py.get() != 0);
  743. BOOST_TEST(py->use_count() == 1);
  744. }
  745. BOOST_TEST( N::base::instances == 0 );
  746. }
  747. } // namespace n_dynamic_cast
  748. namespace n_transitive
  749. {
  750. struct X: public N::base
  751. {
  752. boost::intrusive_ptr<X> next;
  753. };
  754. void test()
  755. {
  756. boost::intrusive_ptr<X> p(new X);
  757. p->next = boost::intrusive_ptr<X>(new X);
  758. BOOST_TEST(!p->next->next);
  759. p = p->next;
  760. BOOST_TEST(!p->next);
  761. }
  762. } // namespace n_transitive
  763. namespace n_report_1
  764. {
  765. class foo: public N::base
  766. {
  767. public:
  768. foo(): m_self(this)
  769. {
  770. }
  771. void suicide()
  772. {
  773. m_self = 0;
  774. }
  775. private:
  776. boost::intrusive_ptr<foo> m_self;
  777. };
  778. void test()
  779. {
  780. foo * foo_ptr = new foo;
  781. foo_ptr->suicide();
  782. }
  783. } // namespace n_report_1
  784. int main()
  785. {
  786. n_element_type::test();
  787. n_constructors::test();
  788. n_destructor::test();
  789. n_assignment::test();
  790. n_reset::test();
  791. n_access::test();
  792. n_swap::test();
  793. n_comparison::test();
  794. n_static_cast::test();
  795. n_const_cast::test();
  796. n_dynamic_cast::test();
  797. n_transitive::test();
  798. n_report_1::test();
  799. return boost::report_errors();
  800. }