set_test.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2004-2013. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #include <boost/container/detail/config_begin.hpp>
  11. #include <set>
  12. #include <boost/container/set.hpp>
  13. #include <boost/container/adaptive_pool.hpp>
  14. #include "print_container.hpp"
  15. #include "movable_int.hpp"
  16. #include "dummy_test_allocator.hpp"
  17. #include "set_test.hpp"
  18. #include "propagate_allocator_test.hpp"
  19. #include "emplace_test.hpp"
  20. #include "../../intrusive/test/iterator_test.hpp"
  21. using namespace boost::container;
  22. //Test recursive structures
  23. class recursive_set
  24. {
  25. public:
  26. recursive_set & operator=(const recursive_set &x)
  27. { id_ = x.id_; set_ = x.set_; return *this; }
  28. int id_;
  29. set<recursive_set> set_;
  30. set<recursive_set>::iterator it_;
  31. set<recursive_set>::const_iterator cit_;
  32. set<recursive_set>::reverse_iterator rit_;
  33. set<recursive_set>::const_reverse_iterator crit_;
  34. friend bool operator< (const recursive_set &a, const recursive_set &b)
  35. { return a.id_ < b.id_; }
  36. };
  37. //Test recursive structures
  38. class recursive_multiset
  39. {
  40. public:
  41. recursive_multiset & operator=(const recursive_multiset &x)
  42. { id_ = x.id_; multiset_ = x.multiset_; return *this; }
  43. int id_;
  44. multiset<recursive_multiset> multiset_;
  45. multiset<recursive_multiset>::iterator it_;
  46. multiset<recursive_multiset>::const_iterator cit_;
  47. multiset<recursive_multiset>::reverse_iterator rit_;
  48. multiset<recursive_multiset>::const_reverse_iterator crit_;
  49. friend bool operator< (const recursive_multiset &a, const recursive_multiset &b)
  50. { return a.id_ < b.id_; }
  51. };
  52. template<class C>
  53. void test_move()
  54. {
  55. //Now test move semantics
  56. C original;
  57. original.emplace();
  58. C move_ctor(boost::move(original));
  59. C move_assign;
  60. move_assign.emplace();
  61. move_assign = boost::move(move_ctor);
  62. move_assign.swap(original);
  63. }
  64. bool node_type_test()
  65. {
  66. using namespace boost::container;
  67. {
  68. typedef set<test::movable_int> set_type;
  69. set_type src;
  70. {
  71. test::movable_int mv_1(1), mv_2(2), mv_3(3);
  72. src.emplace(boost::move(mv_1));
  73. src.emplace(boost::move(mv_2));
  74. src.emplace(boost::move(mv_3));
  75. }
  76. if(src.size() != 3)
  77. return false;
  78. set_type dst;
  79. {
  80. test::movable_int mv_3(3);
  81. dst.emplace(boost::move(mv_3));
  82. }
  83. if(dst.size() != 1)
  84. return false;
  85. const test::movable_int mv_1(1);
  86. const test::movable_int mv_2(2);
  87. const test::movable_int mv_3(3);
  88. const test::movable_int mv_33(33);
  89. set_type::insert_return_type r;
  90. r = dst.insert(src.extract(mv_33)); // Key version, try to insert empty node
  91. if(! (r.position == dst.end() && r.inserted == false && r.node.empty()) )
  92. return false;
  93. r = dst.insert(src.extract(src.find(mv_1))); // Iterator version, successful
  94. if(! (r.position == dst.find(mv_1) && r.inserted == true && r.node.empty()) )
  95. return false;
  96. r = dst.insert(dst.begin(), src.extract(mv_2)); // Key type version, successful
  97. if(! (r.position == dst.find(mv_2) && r.inserted == true && r.node.empty()) )
  98. return false;
  99. r = dst.insert(src.extract(mv_3)); // Key type version, unsuccessful
  100. if(!src.empty())
  101. return false;
  102. if(dst.size() != 3)
  103. return false;
  104. if(! (r.position == dst.find(mv_3) && r.inserted == false && r.node.value() == mv_3) )
  105. return false;
  106. }
  107. {
  108. typedef multiset<test::movable_int> multiset_type;
  109. multiset_type src;
  110. {
  111. test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_3bis(3);
  112. src.emplace(boost::move(mv_1));
  113. src.emplace(boost::move(mv_2));
  114. src.emplace(boost::move(mv_3));
  115. src.emplace_hint(src.begin(), boost::move(mv_3bis));
  116. }
  117. if(src.size() != 4)
  118. return false;
  119. multiset_type dst;
  120. {
  121. test::movable_int mv_3(3);
  122. dst.emplace(boost::move(mv_3));
  123. }
  124. if(dst.size() != 1)
  125. return false;
  126. const test::movable_int mv_1(1);
  127. const test::movable_int mv_2(2);
  128. const test::movable_int mv_3(3);
  129. const test::movable_int mv_4(4);
  130. multiset_type::iterator r;
  131. multiset_type::node_type nt(src.extract(mv_3));
  132. r = dst.insert(dst.begin(), boost::move(nt));
  133. if(! (*r == mv_3 && dst.find(mv_3) == r && nt.empty()) )
  134. return false;
  135. nt = src.extract(src.find(mv_1));
  136. r = dst.insert(boost::move(nt)); // Iterator version, successful
  137. if(! (*r == mv_1 && nt.empty()) )
  138. return false;
  139. nt = src.extract(mv_2);
  140. r = dst.insert(boost::move(nt)); // Key type version, successful
  141. if(! (*r == mv_2 && nt.empty()) )
  142. return false;
  143. r = dst.insert(src.extract(mv_3)); // Key type version, successful
  144. if(! (*r == mv_3 && r == --multiset_type::iterator(dst.upper_bound(mv_3)) && nt.empty()) )
  145. return false;
  146. r = dst.insert(src.extract(mv_4)); // Key type version, unsuccessful
  147. if(! (r == dst.end()) )
  148. return false;
  149. if(!src.empty())
  150. return false;
  151. if(dst.size() != 5)
  152. return false;
  153. }
  154. return true;
  155. }
  156. struct boost_container_set;
  157. struct boost_container_multiset;
  158. namespace boost {
  159. namespace container {
  160. namespace test {
  161. template<>
  162. struct alloc_propagate_base<boost_container_set>
  163. {
  164. template <class T, class Allocator>
  165. struct apply
  166. {
  167. typedef boost::container::set<T, std::less<T>, Allocator> type;
  168. };
  169. };
  170. template<>
  171. struct alloc_propagate_base<boost_container_multiset>
  172. {
  173. template <class T, class Allocator>
  174. struct apply
  175. {
  176. typedef boost::container::multiset<T, std::less<T>, Allocator> type;
  177. };
  178. };
  179. bool constructor_template_auto_deduction_test()
  180. {
  181. #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
  182. using namespace boost::container;
  183. const std::size_t NumElements = 100;
  184. {
  185. std::set<int> int_set;
  186. for (std::size_t i = 0; i != NumElements; ++i) {
  187. int_set.insert(static_cast<int>(i));
  188. }
  189. std::multiset<int> int_mset;
  190. for (std::size_t i = 0; i != NumElements; ++i) {
  191. int_mset.insert(static_cast<int>(i));
  192. }
  193. typedef std::less<int> comp_int_t;
  194. typedef std::allocator<int> alloc_int_t;
  195. //range
  196. {
  197. auto fset = set(int_set.begin(), int_set.end());
  198. if (!CheckEqualContainers(int_set, fset))
  199. return false;
  200. auto fmset = multiset(int_mset.begin(), int_mset.end());
  201. if (!CheckEqualContainers(int_mset, fmset))
  202. return false;
  203. }
  204. //range+comp
  205. {
  206. auto fset = set(int_set.begin(), int_set.end(), comp_int_t());
  207. if (!CheckEqualContainers(int_set, fset))
  208. return false;
  209. auto fmset = multiset(int_mset.begin(), int_mset.end(), comp_int_t());
  210. if (!CheckEqualContainers(int_mset, fmset))
  211. return false;
  212. }
  213. //range+comp+alloc
  214. {
  215. auto fset = set(int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t());
  216. if (!CheckEqualContainers(int_set, fset))
  217. return false;
  218. auto fmset = multiset(int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t());
  219. if (!CheckEqualContainers(int_mset, fmset))
  220. return false;
  221. }
  222. //range+alloc
  223. {
  224. auto fset = set(int_set.begin(), int_set.end(), alloc_int_t());
  225. if (!CheckEqualContainers(int_set, fset))
  226. return false;
  227. auto fmset = multiset(int_mset.begin(), int_mset.end(), alloc_int_t());
  228. if (!CheckEqualContainers(int_mset, fmset))
  229. return false;
  230. }
  231. //ordered_unique_range / ordered_range
  232. //range
  233. {
  234. auto fset = set(ordered_unique_range, int_set.begin(), int_set.end());
  235. if (!CheckEqualContainers(int_set, fset))
  236. return false;
  237. auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end());
  238. if (!CheckEqualContainers(int_mset, fmset))
  239. return false;
  240. }
  241. //range+comp
  242. {
  243. auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t());
  244. if (!CheckEqualContainers(int_set, fset))
  245. return false;
  246. auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t());
  247. if (!CheckEqualContainers(int_mset, fmset))
  248. return false;
  249. }
  250. //range+comp+alloc
  251. {
  252. auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t());
  253. if (!CheckEqualContainers(int_set, fset))
  254. return false;
  255. auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t());
  256. if (!CheckEqualContainers(int_mset, fmset))
  257. return false;
  258. }
  259. //range+alloc
  260. {
  261. auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), alloc_int_t());
  262. if (!CheckEqualContainers(int_set, fset))
  263. return false;
  264. auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), alloc_int_t());
  265. if (!CheckEqualContainers(int_mset, fmset))
  266. return false;
  267. }
  268. }
  269. #endif
  270. return true;
  271. }
  272. }}} //boost::container::test
  273. template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
  274. struct GetAllocatorSet
  275. {
  276. template<class ValueType>
  277. struct apply
  278. {
  279. typedef set < ValueType
  280. , std::less<ValueType>
  281. , typename allocator_traits<VoidAllocator>
  282. ::template portable_rebind_alloc<ValueType>::type
  283. , typename boost::container::tree_assoc_options
  284. < boost::container::tree_type<tree_type_value>
  285. >::type
  286. > set_type;
  287. typedef multiset < ValueType
  288. , std::less<ValueType>
  289. , typename allocator_traits<VoidAllocator>
  290. ::template portable_rebind_alloc<ValueType>::type
  291. , typename boost::container::tree_assoc_options
  292. < boost::container::tree_type<tree_type_value>
  293. >::type
  294. > multiset_type;
  295. };
  296. };
  297. void test_merge_from_different_comparison()
  298. {
  299. set<int> set1;
  300. set<int, std::greater<int> > set2;
  301. set1.merge(set2);
  302. }
  303. bool test_heterogeneous_lookups()
  304. {
  305. typedef set<int, test::less_transparent> set_t;
  306. typedef multiset<int, test::less_transparent> mset_t;
  307. set_t set1;
  308. mset_t mset1;
  309. const set_t &cset1 = set1;
  310. const mset_t &cmset1 = mset1;
  311. set1.insert(1);
  312. set1.insert(1);
  313. set1.insert(2);
  314. set1.insert(2);
  315. set1.insert(3);
  316. mset1.insert(1);
  317. mset1.insert(1);
  318. mset1.insert(2);
  319. mset1.insert(2);
  320. mset1.insert(3);
  321. const test::non_copymovable_int find_me(2);
  322. //find
  323. if(*set1.find(find_me) != 2)
  324. return false;
  325. if(*cset1.find(find_me) != 2)
  326. return false;
  327. if(*mset1.find(find_me) != 2)
  328. return false;
  329. if(*cmset1.find(find_me) != 2)
  330. return false;
  331. //count
  332. if(set1.count(find_me) != 1)
  333. return false;
  334. if(cset1.count(find_me) != 1)
  335. return false;
  336. if(mset1.count(find_me) != 2)
  337. return false;
  338. if(cmset1.count(find_me) != 2)
  339. return false;
  340. //contains
  341. if(!set1.contains(find_me))
  342. return false;
  343. if(!cset1.contains(find_me))
  344. return false;
  345. if(!mset1.contains(find_me))
  346. return false;
  347. if(!cmset1.contains(find_me))
  348. return false;
  349. //lower_bound
  350. if(*set1.lower_bound(find_me) != 2)
  351. return false;
  352. if(*cset1.lower_bound(find_me) != 2)
  353. return false;
  354. if(*mset1.lower_bound(find_me) != 2)
  355. return false;
  356. if(*cmset1.lower_bound(find_me) != 2)
  357. return false;
  358. //upper_bound
  359. if(*set1.upper_bound(find_me) != 3)
  360. return false;
  361. if(*cset1.upper_bound(find_me) != 3)
  362. return false;
  363. if(*mset1.upper_bound(find_me) != 3)
  364. return false;
  365. if(*cmset1.upper_bound(find_me) != 3)
  366. return false;
  367. //equal_range
  368. if(*set1.equal_range(find_me).first != 2)
  369. return false;
  370. if(*cset1.equal_range(find_me).second != 3)
  371. return false;
  372. if(*mset1.equal_range(find_me).first != 2)
  373. return false;
  374. if(*cmset1.equal_range(find_me).second != 3)
  375. return false;
  376. return true;
  377. }
  378. int main ()
  379. {
  380. //Recursive container instantiation
  381. {
  382. set<recursive_set> set_;
  383. multiset<recursive_multiset> multiset_;
  384. }
  385. //Allocator argument container
  386. {
  387. set<int> set_((set<int>::allocator_type()));
  388. multiset<int> multiset_((multiset<int>::allocator_type()));
  389. }
  390. //Now test move semantics
  391. {
  392. test_move<set<recursive_set> >();
  393. test_move<multiset<recursive_multiset> >();
  394. }
  395. //Test std::pair value type as tree has workarounds to make old std::pair
  396. //implementations movable that can break things
  397. {
  398. boost::container::set<std::pair<int,int> > s;
  399. std::pair<int,int> p(0, 0);
  400. s.insert(p);
  401. s.emplace(p);
  402. }
  403. if (!boost::container::test::instantiate_constructors<set<int>, multiset<int> >())
  404. return 1;
  405. test_merge_from_different_comparison();
  406. ////////////////////////////////////
  407. // Constructor Template Auto Deduction test
  408. ////////////////////////////////////
  409. if (!test::constructor_template_auto_deduction_test()) {
  410. return 1;
  411. }
  412. if(!test_heterogeneous_lookups())
  413. return 1;
  414. ////////////////////////////////////
  415. // Testing allocator implementations
  416. ////////////////////////////////////
  417. {
  418. typedef std::set<int> MyStdSet;
  419. typedef std::multiset<int> MyStdMultiSet;
  420. if (0 != test::set_test
  421. < GetAllocatorSet<std::allocator<void>, red_black_tree>::apply<int>::set_type
  422. , MyStdSet
  423. , GetAllocatorSet<std::allocator<void>, red_black_tree>::apply<int>::multiset_type
  424. , MyStdMultiSet>()) {
  425. std::cout << "Error in set_test<std::allocator<void>, red_black_tree>" << std::endl;
  426. return 1;
  427. }
  428. if (0 != test::set_test
  429. < GetAllocatorSet<new_allocator<void>, avl_tree>::apply<int>::set_type
  430. , MyStdSet
  431. , GetAllocatorSet<new_allocator<void>, avl_tree>::apply<int>::multiset_type
  432. , MyStdMultiSet>()) {
  433. std::cout << "Error in set_test<new_allocator<void>, avl_tree>" << std::endl;
  434. return 1;
  435. }
  436. if (0 != test::set_test
  437. < GetAllocatorSet<adaptive_pool<void>, scapegoat_tree>::apply<int>::set_type
  438. , MyStdSet
  439. , GetAllocatorSet<adaptive_pool<void>, scapegoat_tree>::apply<int>::multiset_type
  440. , MyStdMultiSet>()) {
  441. std::cout << "Error in set_test<adaptive_pool<void>, scapegoat_tree>" << std::endl;
  442. return 1;
  443. }
  444. ///////////
  445. if (0 != test::set_test
  446. < GetAllocatorSet<new_allocator<void>, splay_tree>::apply<test::movable_int>::set_type
  447. , MyStdSet
  448. , GetAllocatorSet<new_allocator<void>, splay_tree>::apply<test::movable_int>::multiset_type
  449. , MyStdMultiSet>()) {
  450. std::cout << "Error in set_test<new_allocator<void>, splay_tree>" << std::endl;
  451. return 1;
  452. }
  453. if (0 != test::set_test
  454. < GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::set_type
  455. , MyStdSet
  456. , GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::multiset_type
  457. , MyStdMultiSet>()) {
  458. std::cout << "Error in set_test<new_allocator<void>, red_black_tree>" << std::endl;
  459. return 1;
  460. }
  461. if (0 != test::set_test
  462. < GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::set_type
  463. , MyStdSet
  464. , GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::multiset_type
  465. , MyStdMultiSet>()) {
  466. std::cout << "Error in set_test<new_allocator<void>, red_black_tree>" << std::endl;
  467. return 1;
  468. }
  469. }
  470. ////////////////////////////////////
  471. // Emplace testing
  472. ////////////////////////////////////
  473. const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC);
  474. if(!boost::container::test::test_emplace<set<test::EmplaceInt>, SetOptions>())
  475. return 1;
  476. if(!boost::container::test::test_emplace<multiset<test::EmplaceInt>, SetOptions>())
  477. return 1;
  478. ////////////////////////////////////
  479. // Allocator propagation testing
  480. ////////////////////////////////////
  481. if(!boost::container::test::test_propagate_allocator<boost_container_set>())
  482. return 1;
  483. if(!boost::container::test::test_propagate_allocator<boost_container_multiset>())
  484. return 1;
  485. if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<set<int> >())
  486. return 1;
  487. if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<multiset<int> >())
  488. return 1;
  489. ////////////////////////////////////
  490. // Test optimize_size option
  491. ////////////////////////////////////
  492. //
  493. // set
  494. //
  495. typedef set< int*, std::less<int*>, std::allocator<int*>
  496. , tree_assoc_options< optimize_size<false>, tree_type<red_black_tree> >::type > rbset_size_optimized_no;
  497. typedef set< int*, std::less<int*>, std::allocator<int*>
  498. , tree_assoc_options< optimize_size<true>, tree_type<avl_tree> >::type > avlset_size_optimized_yes;
  499. //
  500. // multiset
  501. //
  502. typedef multiset< int*, std::less<int*>, std::allocator<int*>
  503. , tree_assoc_options< optimize_size<true>, tree_type<red_black_tree> >::type > rbmset_size_optimized_yes;
  504. typedef multiset< int*, std::less<int*>, std::allocator<int*>
  505. , tree_assoc_options< optimize_size<false>, tree_type<avl_tree> >::type > avlmset_size_optimized_no;
  506. BOOST_STATIC_ASSERT(sizeof(rbmset_size_optimized_yes) < sizeof(rbset_size_optimized_no));
  507. BOOST_STATIC_ASSERT(sizeof(avlset_size_optimized_yes) < sizeof(avlmset_size_optimized_no));
  508. ////////////////////////////////////
  509. // Iterator testing
  510. ////////////////////////////////////
  511. {
  512. typedef boost::container::set<int> cont_int;
  513. cont_int a; a.insert(0); a.insert(1); a.insert(2);
  514. boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
  515. if(boost::report_errors() != 0) {
  516. return 1;
  517. }
  518. }
  519. {
  520. typedef boost::container::multiset<int> cont_int;
  521. cont_int a; a.insert(0); a.insert(1); a.insert(2);
  522. boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
  523. if(boost::report_errors() != 0) {
  524. return 1;
  525. }
  526. }
  527. ////////////////////////////////////
  528. // Node extraction/insertion testing functions
  529. ////////////////////////////////////
  530. if(!node_type_test())
  531. return 1;
  532. ////////////////////////////////////
  533. // has_trivial_destructor_after_move testing
  534. ////////////////////////////////////
  535. // set, default allocator
  536. {
  537. typedef boost::container::set<int> cont;
  538. typedef boost::container::dtl::tree<int, void, std::less<int>, void, void> tree;
  539. if (boost::has_trivial_destructor_after_move<cont>::value !=
  540. boost::has_trivial_destructor_after_move<tree>::value) {
  541. std::cerr << "has_trivial_destructor_after_move(set, default allocator) test failed" << std::endl;
  542. return 1;
  543. }
  544. }
  545. // set, std::allocator
  546. {
  547. typedef boost::container::set<int, std::less<int>, std::allocator<int> > cont;
  548. typedef boost::container::dtl::tree<int, void, std::less<int>, std::allocator<int>, void> tree;
  549. if (boost::has_trivial_destructor_after_move<cont>::value !=
  550. boost::has_trivial_destructor_after_move<tree>::value) {
  551. std::cerr << "has_trivial_destructor_after_move(set, std::allocator) test failed" << std::endl;
  552. return 1;
  553. }
  554. }
  555. // multiset, default allocator
  556. {
  557. typedef boost::container::multiset<int> cont;
  558. typedef boost::container::dtl::tree<int, void, std::less<int>, void, void> tree;
  559. if (boost::has_trivial_destructor_after_move<cont>::value !=
  560. boost::has_trivial_destructor_after_move<tree>::value) {
  561. std::cerr << "has_trivial_destructor_after_move(multiset, default allocator) test failed" << std::endl;
  562. return 1;
  563. }
  564. }
  565. // multiset, std::allocator
  566. {
  567. typedef boost::container::multiset<int, std::less<int>, std::allocator<int> > cont;
  568. typedef boost::container::dtl::tree<int, void, std::less<int>, std::allocator<int>, void> tree;
  569. if (boost::has_trivial_destructor_after_move<cont>::value !=
  570. boost::has_trivial_destructor_after_move<tree>::value) {
  571. std::cerr << "has_trivial_destructor_after_move(multiset, std::allocator) test failed" << std::endl;
  572. return 1;
  573. }
  574. }
  575. return 0;
  576. }
  577. #include <boost/container/detail/config_end.hpp>