test_container.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2007-2013
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // See http://www.boost.org/libs/intrusive for documentation.
  10. //
  11. /////////////////////////////////////////////////////////////////////////////
  12. #ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP
  13. #define BOOST_INTRUSIVE_TEST_CONTAINER_HPP
  14. #include <boost/detail/lightweight_test.hpp>
  15. #include <boost/intrusive/detail/mpl.hpp>
  16. #include <boost/intrusive/detail/simple_disposers.hpp>
  17. #include <boost/intrusive/detail/iterator.hpp>
  18. #include <boost/move/utility_core.hpp>
  19. #include <boost/move/adl_move_swap.hpp>
  20. #include <boost/intrusive/detail/mpl.hpp>
  21. #include <boost/static_assert.hpp>
  22. #include "iterator_test.hpp"
  23. #include <cstdlib>
  24. namespace boost {
  25. namespace intrusive {
  26. namespace test {
  27. BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(is_unordered, hasher)
  28. template<class Container>
  29. struct test_container_typedefs
  30. {
  31. typedef typename Container::value_type value_type;
  32. typedef typename Container::iterator iterator;
  33. typedef typename Container::const_iterator const_iterator;
  34. typedef typename Container::reference reference;
  35. typedef typename Container::const_reference const_reference;
  36. typedef typename Container::pointer pointer;
  37. typedef typename Container::const_pointer const_pointer;
  38. typedef typename Container::difference_type difference_type;
  39. typedef typename Container::size_type size_type;
  40. typedef typename Container::value_traits value_traits;
  41. };
  42. template< class Container >
  43. void test_container( Container & c )
  44. {
  45. typedef typename Container::const_iterator const_iterator;
  46. typedef typename Container::iterator iterator;
  47. typedef typename Container::size_type size_type;
  48. {test_container_typedefs<Container> dummy; (void)dummy;}
  49. const size_type num_elem = c.size();
  50. BOOST_TEST( c.empty() == (num_elem == 0) );
  51. {
  52. iterator it(c.begin()), itend(c.end());
  53. size_type i;
  54. for(i = 0; i < num_elem; ++i){
  55. ++it;
  56. }
  57. BOOST_TEST( it == itend );
  58. BOOST_TEST( c.size() == i );
  59. }
  60. //Check iterator conversion
  61. BOOST_TEST(const_iterator(c.begin()) == c.cbegin() );
  62. {
  63. const_iterator it(c.cbegin()), itend(c.cend());
  64. size_type i;
  65. for(i = 0; i < num_elem; ++i){
  66. ++it;
  67. }
  68. BOOST_TEST( it == itend );
  69. BOOST_TEST( c.size() == i );
  70. }
  71. static_cast<const Container&>(c).check();
  72. //Very basic test for comparisons
  73. {
  74. BOOST_TEST(c == c);
  75. BOOST_TEST(!(c != c));
  76. BOOST_TEST(!(c < c));
  77. BOOST_TEST(c <= c);
  78. BOOST_TEST(!(c > c));
  79. BOOST_TEST(c >= c);
  80. }
  81. }
  82. template< class Container, class Data >
  83. void test_sequence_container(Container & c, Data & d)
  84. {
  85. assert( d.size() > 2 );
  86. {
  87. c.clear();
  88. BOOST_TEST( c.size() == 0 );
  89. BOOST_TEST( c.empty() );
  90. {
  91. typename Data::iterator i = d.begin();
  92. c.insert( c.begin(), *i );
  93. BOOST_TEST( &*c.iterator_to(*c.begin()) == &*i );
  94. BOOST_TEST( &*c.iterator_to(*c.cbegin()) == &*i );
  95. BOOST_TEST( &*Container::s_iterator_to(*c.begin()) == &*i );
  96. BOOST_TEST( &*Container::s_iterator_to(*c.cbegin()) == &*i );
  97. c.insert( c.end(), *(++i) );
  98. }
  99. BOOST_TEST( c.size() == 2 );
  100. BOOST_TEST( !c.empty() );
  101. typename Container::iterator i;
  102. i = c.erase( c.begin() );
  103. BOOST_TEST( c.size() == 1 );
  104. BOOST_TEST( !c.empty() );
  105. i = c.erase( c.begin() );
  106. BOOST_TEST( c.size() == 0 );
  107. BOOST_TEST( c.empty() );
  108. c.insert( c.begin(), *d.begin() );
  109. BOOST_TEST( c.size() == 1 );
  110. BOOST_TEST( !c.empty() );
  111. {
  112. typename Data::iterator di = d.begin();
  113. ++++di;
  114. c.insert( c.begin(), *(di) );
  115. }
  116. i = c.erase( c.begin(), c.end() );
  117. BOOST_TEST( i == c.end() );
  118. BOOST_TEST( c.empty() );
  119. c.insert( c.begin(), *d.begin() );
  120. BOOST_TEST( c.size() == 1 );
  121. BOOST_TEST( c.begin() != c.end() );
  122. i = c.erase_and_dispose( c.begin(), detail::null_disposer() );
  123. BOOST_TEST( i == c.begin() );
  124. c.assign(d.begin(), d.end());
  125. BOOST_TEST( c.size() == d.size() );
  126. c.clear();
  127. BOOST_TEST( c.size() == 0 );
  128. BOOST_TEST( c.empty() );
  129. }
  130. {
  131. c.clear();
  132. c.insert( c.begin(), d.begin(), d.end() );
  133. Container move_c(::boost::move(c));
  134. BOOST_TEST( move_c.size() == d.size() );
  135. BOOST_TEST( c.empty());
  136. c = ::boost::move(move_c);
  137. BOOST_TEST( c.size() == d.size() );
  138. BOOST_TEST( move_c.empty());
  139. }
  140. }
  141. template< class Container, class Data >
  142. void test_common_unordered_and_associative_container(Container & c, Data & d, boost::intrusive::detail::true_ unordered)
  143. {
  144. (void)unordered;
  145. typedef typename Container::size_type size_type;
  146. typedef typename Container::key_of_value key_of_value;
  147. typedef typename Container::iterator iterator;
  148. typedef typename Container::const_iterator const_iterator;
  149. assert( d.size() > 2 );
  150. c.clear();
  151. c.insert(d.begin(), d.end());
  152. {
  153. Container const &cc = c;
  154. for( typename Data::const_iterator di = d.begin(), de = d.end();
  155. di != de; ++di )
  156. {
  157. BOOST_TEST( cc.find(key_of_value()(*di), c.hash_function(), c.key_eq()) != cc.end() );
  158. std::pair<const_iterator, const_iterator> rdi = cc.equal_range(key_of_value()(*di), c.hash_function(), c.key_eq());
  159. BOOST_TEST(rdi.first != rdi.second);
  160. BOOST_TEST(size_type(boost::intrusive::iterator_distance(rdi.first, rdi.second)) == cc.count(key_of_value()(*di), c.hash_function(), c.key_eq()));
  161. }
  162. for( iterator ci = c.begin(), ce = c.end(); ci != ce; )
  163. {
  164. BOOST_TEST( c.find(key_of_value()(*ci)) != c.end() );
  165. std::pair<iterator, iterator> rci = c.equal_range(key_of_value()(*ci), c.hash_function(), c.key_eq());
  166. BOOST_TEST(rci.first != rci.second);
  167. size_type const sc = c.count(key_of_value()(*ci), c.hash_function(), c.key_eq());
  168. BOOST_TEST(size_type(boost::intrusive::iterator_distance(rci.first, rci.second)) == sc);
  169. BOOST_TEST(sc == c.erase(key_of_value()(*ci), c.hash_function(), c.key_eq()));
  170. ci = rci.second;
  171. }
  172. BOOST_TEST(c.empty());
  173. }
  174. c.clear();
  175. c.insert(d.begin(), d.end());
  176. typename Data::const_iterator db = d.begin();
  177. typename Data::const_iterator da = db++;
  178. size_type old_size = c.size();
  179. c.erase(key_of_value()(*da), c.hash_function(), c.key_eq());
  180. BOOST_TEST( c.size() == old_size-1 );
  181. //This should not eras anyone
  182. size_type second_erase = c.erase_and_dispose
  183. ( key_of_value()(*da), c.hash_function(), c.key_eq(), detail::null_disposer() );
  184. BOOST_TEST( second_erase == 0 );
  185. BOOST_TEST( c.count(key_of_value()(*da), c.hash_function(), c.key_eq()) == 0 );
  186. BOOST_TEST( c.count(key_of_value()(*db), c.hash_function(), c.key_eq()) != 0 );
  187. BOOST_TEST( c.find(key_of_value()(*da), c.hash_function(), c.key_eq()) == c.end() );
  188. BOOST_TEST( c.find(key_of_value()(*db), c.hash_function(), c.key_eq()) != c.end() );
  189. BOOST_TEST( c.equal_range(key_of_value()(*db), c.hash_function(), c.key_eq()).first != c.end() );
  190. c.clear();
  191. BOOST_TEST( c.equal_range(key_of_value()(*da), c.hash_function(), c.key_eq()).first == c.end() );
  192. //
  193. //suggested_upper_bucket_count
  194. //
  195. //Maximum fallbacks to the highest possible value
  196. typename Container::size_type sz = Container::suggested_upper_bucket_count(size_type(-1));
  197. BOOST_TEST( sz > size_type(-1)/2 );
  198. //In the rest of cases the upper bound is returned
  199. sz = Container::suggested_upper_bucket_count(size_type(-1)/2);
  200. BOOST_TEST( sz >= size_type(-1)/2 );
  201. sz = Container::suggested_upper_bucket_count(size_type(-1)/4);
  202. BOOST_TEST( sz >= size_type(-1)/4 );
  203. sz = Container::suggested_upper_bucket_count(0);
  204. BOOST_TEST( sz > 0 );
  205. //
  206. //suggested_lower_bucket_count
  207. //
  208. sz = Container::suggested_lower_bucket_count(size_type(-1));
  209. BOOST_TEST( sz <= size_type(-1) );
  210. //In the rest of cases the lower bound is returned
  211. sz = Container::suggested_lower_bucket_count(size_type(-1)/2);
  212. BOOST_TEST( sz <= size_type(-1)/2 );
  213. sz = Container::suggested_lower_bucket_count(size_type(-1)/4);
  214. BOOST_TEST( sz <= size_type(-1)/4 );
  215. //Minimum fallbacks to the lowest possible value
  216. sz = Container::suggested_upper_bucket_count(0);
  217. BOOST_TEST( sz > 0 );
  218. }
  219. template< class Container, class Data >
  220. void test_common_unordered_and_associative_container(Container & c, Data & d, boost::intrusive::detail::false_ unordered)
  221. {
  222. (void)unordered;
  223. typedef typename Container::size_type size_type;
  224. typedef typename Container::key_of_value key_of_value;
  225. typedef typename Container::iterator iterator;
  226. typedef typename Container::const_iterator const_iterator;
  227. assert( d.size() > 2 );
  228. c.clear();
  229. typename Container::reference r = *d.begin();
  230. c.insert(d.begin(), ++d.begin());
  231. BOOST_TEST( &*Container::s_iterator_to(*c.begin()) == &r );
  232. BOOST_TEST( &*Container::s_iterator_to(*c.cbegin()) == &r );
  233. c.clear();
  234. c.insert(d.begin(), d.end());
  235. {
  236. Container const &cc = c;
  237. for( typename Data::const_iterator di = d.begin(), de = d.end();
  238. di != de; ++di )
  239. {
  240. BOOST_TEST( cc.find(key_of_value()(*di), c.key_comp()) != cc.end() );
  241. std::pair<const_iterator, const_iterator> rdi = cc.equal_range(key_of_value()(*di), c.key_comp());
  242. BOOST_TEST(rdi.first != rdi.second);
  243. BOOST_TEST(size_type(boost::intrusive::iterator_distance(rdi.first, rdi.second)) == cc.count(key_of_value()(*di), c.key_comp()));
  244. }
  245. for( iterator ci = c.begin(), ce = c.end(); ci != ce; )
  246. {
  247. BOOST_TEST( c.find(key_of_value()(*ci)) != c.end() );
  248. std::pair<iterator, iterator> rci = c.equal_range(key_of_value()(*ci), c.key_comp());
  249. BOOST_TEST(rci.first != rci.second);
  250. size_type const sc = c.count(key_of_value()(*ci), c.key_comp());
  251. BOOST_TEST(size_type(boost::intrusive::iterator_distance(rci.first, rci.second)) == sc);
  252. BOOST_TEST(sc == c.erase(key_of_value()(*ci), c.key_comp()));
  253. ci = rci.second;
  254. }
  255. BOOST_TEST(c.empty());
  256. }
  257. c.clear();
  258. c.insert(d.begin(), d.end());
  259. typename Data::const_iterator db = d.begin();
  260. typename Data::const_iterator da = db++;
  261. size_type old_size = c.size();
  262. c.erase(key_of_value()(*da), c.key_comp());
  263. BOOST_TEST( c.size() == old_size-1 );
  264. //This should not erase any
  265. size_type second_erase = c.erase_and_dispose( key_of_value()(*da), c.key_comp(), detail::null_disposer() );
  266. BOOST_TEST( second_erase == 0 );
  267. BOOST_TEST( c.count(key_of_value()(*da), c.key_comp()) == 0 );
  268. BOOST_TEST( c.count(key_of_value()(*db), c.key_comp()) != 0 );
  269. BOOST_TEST( c.find(key_of_value()(*da), c.key_comp()) == c.end() );
  270. BOOST_TEST( c.find(key_of_value()(*db), c.key_comp()) != c.end() );
  271. BOOST_TEST( c.equal_range(key_of_value()(*db), c.key_comp()).first != c.end() );
  272. c.clear();
  273. BOOST_TEST( c.equal_range(key_of_value()(*da), c.key_comp()).first == c.end() );
  274. }
  275. template< class Container, class Data >
  276. void test_common_unordered_and_associative_container(Container & c, Data & d)
  277. {
  278. typedef typename Container::size_type size_type;
  279. typedef typename Container::key_of_value key_of_value;
  280. typedef typename Container::iterator iterator;
  281. typedef typename Container::const_iterator const_iterator;
  282. {
  283. assert( d.size() > 2 );
  284. c.clear();
  285. typename Container::reference r = *d.begin();
  286. c.insert(d.begin(), ++d.begin());
  287. BOOST_TEST( &*c.iterator_to(*c.begin()) == &r );
  288. BOOST_TEST( &*c.iterator_to(*c.cbegin()) == &r );
  289. c.clear();
  290. c.insert(d.begin(), d.end());
  291. Container const &cc = c;
  292. for( typename Data::const_iterator di = d.begin(), de = d.end();
  293. di != de; ++di )
  294. {
  295. BOOST_TEST( cc.find(key_of_value()(*di)) != cc.end() );
  296. std::pair<const_iterator, const_iterator> rdi = cc.equal_range(key_of_value()(*di));
  297. BOOST_TEST(rdi.first != rdi.second);
  298. BOOST_TEST(size_type(boost::intrusive::iterator_distance(rdi.first, rdi.second)) == cc.count(key_of_value()(*di)));
  299. }
  300. for( iterator ci = c.begin(), ce = c.end(); ci != ce; )
  301. {
  302. BOOST_TEST( c.find(key_of_value()(*ci)) != c.end() );
  303. std::pair<iterator, iterator> rci = c.equal_range(key_of_value()(*ci));
  304. BOOST_TEST(rci.first != rci.second);
  305. size_type const sc = c.count(key_of_value()(*ci));
  306. BOOST_TEST(size_type(boost::intrusive::iterator_distance(rci.first, rci.second)) == sc);
  307. BOOST_TEST(sc == c.erase(key_of_value()(*ci)));
  308. ci = rci.second;
  309. }
  310. BOOST_TEST(c.empty());
  311. }
  312. {
  313. c.clear();
  314. c.insert(d.begin(), d.end());
  315. typename Data::const_iterator db = d.begin();
  316. typename Data::const_iterator da = db++;
  317. size_type old_size = c.size();
  318. c.erase(key_of_value()(*da));
  319. BOOST_TEST( c.size() == old_size-1 );
  320. //This should erase nothing
  321. size_type second_erase = c.erase_and_dispose( key_of_value()(*da), detail::null_disposer() );
  322. BOOST_TEST( second_erase == 0 );
  323. BOOST_TEST( c.count(key_of_value()(*da)) == 0 );
  324. BOOST_TEST( c.count(key_of_value()(*db)) != 0 );
  325. BOOST_TEST( c.find(key_of_value()(*da)) == c.end() );
  326. BOOST_TEST( c.find(key_of_value()(*db)) != c.end() );
  327. BOOST_TEST( c.equal_range(key_of_value()(*db)).first != c.end() );
  328. BOOST_TEST( c.equal_range(key_of_value()(*da)).first == c.equal_range(key_of_value()(*da)).second );
  329. }
  330. {
  331. c.clear();
  332. c.insert( d.begin(), d.end() );
  333. size_type orig_size = c.size();
  334. Container move_c(::boost::move(c));
  335. BOOST_TEST(orig_size == move_c.size());
  336. BOOST_TEST( c.empty());
  337. for( typename Data::const_iterator di = d.begin(), de = d.end();
  338. di != de; ++di )
  339. { BOOST_TEST( move_c.find(key_of_value()(*di)) != move_c.end() ); }
  340. c = ::boost::move(move_c);
  341. for( typename Data::const_iterator di = d.begin(), de = d.end();
  342. di != de; ++di )
  343. { BOOST_TEST( c.find(key_of_value()(*di)) != c.end() ); }
  344. BOOST_TEST( move_c.empty());
  345. }
  346. typedef detail::bool_<is_unordered<Container>::value> enabler;
  347. test_common_unordered_and_associative_container(c, d, enabler());
  348. }
  349. template< class Container, class Data >
  350. void test_associative_container_invariants(Container & c, Data & d)
  351. {
  352. typedef typename Container::const_iterator const_iterator;
  353. typedef typename Container::key_of_value key_of_value;
  354. for( typename Data::const_iterator di = d.begin(), de = d.end();
  355. di != de; ++di)
  356. {
  357. const_iterator ci = c.find(key_of_value()(*di));
  358. BOOST_TEST( ci != c.end() );
  359. BOOST_TEST( ! c.value_comp()(*ci, *di) );
  360. BOOST_TEST( ! c.key_comp()(key_of_value()(*ci), key_of_value()(*di)) );
  361. const_iterator cil = c.lower_bound(key_of_value()(*di));
  362. const_iterator ciu = c.upper_bound(key_of_value()(*di));
  363. std::pair<const_iterator, const_iterator> er = c.equal_range(key_of_value()(*di));
  364. BOOST_TEST( cil == er.first );
  365. BOOST_TEST( ciu == er.second );
  366. if(ciu != c.end()){
  367. BOOST_TEST( c.value_comp()(*cil, *ciu) );
  368. BOOST_TEST( c.key_comp()(key_of_value()(*cil), key_of_value()(*ciu)) );
  369. }
  370. if(c.count(key_of_value()(*di)) > 1){
  371. const_iterator ci_next = cil; ++ci_next;
  372. for( ; ci_next != ciu; ++cil, ++ci_next){
  373. BOOST_TEST( !c.value_comp()(*ci_next, *cil) );
  374. BOOST_TEST( !c.key_comp()(key_of_value()(*ci_next), key_of_value()(*cil)) );
  375. }
  376. }
  377. }
  378. }
  379. template< class Container, class Data >
  380. void test_associative_container(Container & c, Data & d)
  381. {
  382. assert( d.size() > 2 );
  383. c.clear();
  384. c.insert(d.begin(),d.end());
  385. test_associative_container_invariants(c, d);
  386. const Container & cr = c;
  387. test_associative_container_invariants(cr, d);
  388. }
  389. template< class Container, class Data >
  390. void test_unordered_associative_container_invariants(Container & c, Data & d)
  391. {
  392. typedef typename Container::size_type size_type;
  393. typedef typename Container::const_iterator const_iterator;
  394. typedef typename Container::key_of_value key_of_value;
  395. for( typename Data::const_iterator di = d.begin(), de = d.end() ;
  396. di != de ; ++di ){
  397. const_iterator i = c.find(key_of_value()(*di));
  398. size_type nb = c.bucket(key_of_value()(*i));
  399. size_type bucket_elem = boost::intrusive::iterator_distance(c.begin(nb), c.end(nb));
  400. BOOST_TEST( bucket_elem == c.bucket_size(nb) );
  401. BOOST_TEST( &*c.local_iterator_to(*c.find(key_of_value()(*di))) == &*i );
  402. BOOST_TEST( &*c.local_iterator_to(*const_cast<const Container &>(c).find(key_of_value()(*di))) == &*i );
  403. BOOST_TEST( &*Container::s_local_iterator_to(*c.find(key_of_value()(*di))) == &*i );
  404. BOOST_TEST( &*Container::s_local_iterator_to(*const_cast<const Container &>(c).find(key_of_value()(*di))) == &*i );
  405. std::pair<const_iterator, const_iterator> er = c.equal_range(key_of_value()(*di));
  406. size_type cnt = boost::intrusive::iterator_distance(er.first, er.second);
  407. BOOST_TEST( cnt == c.count(key_of_value()(*di)));
  408. if(cnt > 1){
  409. const_iterator n = er.first;
  410. i = n++;
  411. const_iterator e = er.second;
  412. for(; n != e; ++i, ++n){
  413. BOOST_TEST( c.key_eq()(key_of_value()(*i), key_of_value()(*n)) );
  414. BOOST_TEST( (c.hash_function()(key_of_value()(*i))) == (c.hash_function()(key_of_value()(*n))) );
  415. }
  416. }
  417. }
  418. size_type blen = c.bucket_count();
  419. size_type total_objects = 0;
  420. for(size_type i = 0; i < blen; ++i){
  421. total_objects += c.bucket_size(i);
  422. }
  423. BOOST_TEST( total_objects == c.size() );
  424. }
  425. template< class Container, class Data >
  426. void test_unordered_associative_container(Container & c, Data & d)
  427. {
  428. c.clear();
  429. c.insert( d.begin(), d.end() );
  430. test_unordered_associative_container_invariants(c, d);
  431. const Container & cr = c;
  432. test_unordered_associative_container_invariants(cr, d);
  433. }
  434. template< class Container, class Data >
  435. void test_unique_container(Container & c, Data & d)
  436. {
  437. //typedef typename Container::value_type value_type;
  438. c.clear();
  439. c.insert(d.begin(),d.end());
  440. typename Container::size_type old_size = c.size();
  441. //value_type v(*d.begin());
  442. //c.insert(v);
  443. Data d2(1);
  444. (&d2.front())->value_ = (&d.front())->value_;
  445. c.insert(d2.front());
  446. BOOST_TEST( c.size() == old_size );
  447. c.clear();
  448. }
  449. template< class Container, class Data >
  450. void test_non_unique_container(Container & c, Data & d)
  451. {
  452. //typedef typename Container::value_type value_type;
  453. c.clear();
  454. c.insert(d.begin(),d.end());
  455. typename Container::size_type old_size = c.size();
  456. //value_type v(*d.begin());
  457. //c.insert(v);
  458. Data d2(1);
  459. (&d2.front())->value_ = (&d.front())->value_;
  460. c.insert(d2.front());
  461. BOOST_TEST( c.size() == (old_size+1) );
  462. c.clear();
  463. }
  464. template< class Container, class Data >
  465. void test_maybe_unique_container(Container & c, Data & d, detail::false_)//is_unique
  466. { test_unique_container(c, d); }
  467. template< class Container, class Data >
  468. void test_maybe_unique_container(Container & c, Data & d, detail::true_)//!is_unique
  469. { test_non_unique_container(c, d); }
  470. template< class RandomIt >
  471. void random_shuffle( RandomIt first, RandomIt last )
  472. {
  473. typedef typename boost::intrusive::iterator_traits<RandomIt>::difference_type difference_type;
  474. difference_type n = last - first;
  475. for (difference_type i = n-1; i > 0; --i) {
  476. difference_type j = std::rand() % (i+1);
  477. if(j != i) {
  478. boost::adl_move_swap(first[i], first[j]);
  479. }
  480. }
  481. }
  482. }}}
  483. #endif //#ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP