propagate_allocator_test.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2008. 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. #ifndef BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
  11. #define BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
  12. #include <boost/container/detail/config_begin.hpp>
  13. #include <boost/core/lightweight_test.hpp>
  14. #include "dummy_test_allocator.hpp"
  15. #include <iostream>
  16. namespace boost{
  17. namespace container {
  18. namespace test{
  19. template<class Selector>
  20. struct alloc_propagate_base;
  21. template<class T, class Allocator, class Selector>
  22. class alloc_propagate_wrapper
  23. : public alloc_propagate_base<Selector>::template apply<T, Allocator>::type
  24. {
  25. BOOST_COPYABLE_AND_MOVABLE(alloc_propagate_wrapper)
  26. public:
  27. typedef typename alloc_propagate_base
  28. <Selector>::template apply<T, Allocator>::type Base;
  29. typedef typename Base::allocator_type allocator_type;
  30. typedef typename Base::value_type value_type;
  31. typedef typename Base::size_type size_type;
  32. alloc_propagate_wrapper()
  33. : Base()
  34. {}
  35. explicit alloc_propagate_wrapper(const allocator_type &a)
  36. : Base(a)
  37. {}
  38. /*
  39. //sequence containers only
  40. explicit alloc_propagate_wrapper(size_type n, const value_type &v, const allocator_type &a)
  41. : Base(n, v, a)
  42. {}
  43. alloc_propagate_wrapper(size_type n, const allocator_type &a)
  44. : Base(n, a)
  45. {}*/
  46. template<class Iterator>
  47. alloc_propagate_wrapper(Iterator b, Iterator e, const allocator_type &a)
  48. : Base(b, e, a)
  49. {}
  50. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  51. alloc_propagate_wrapper(std::initializer_list<value_type> il, const allocator_type& a)
  52. : Base(il, a)
  53. {}
  54. /*
  55. //associative containers only
  56. alloc_propagate_wrapper(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
  57. : Base(il, comp, a)
  58. {}*/
  59. #endif
  60. alloc_propagate_wrapper(const alloc_propagate_wrapper &x)
  61. : Base(x)
  62. {}
  63. alloc_propagate_wrapper(const alloc_propagate_wrapper &x, const allocator_type &a)
  64. : Base(x, a)
  65. {}
  66. alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x)
  67. : Base(boost::move(static_cast<Base&>(x)))
  68. {}
  69. alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x, const allocator_type &a)
  70. : Base(boost::move(static_cast<Base&>(x)), a)
  71. {}
  72. alloc_propagate_wrapper &operator=(BOOST_COPY_ASSIGN_REF(alloc_propagate_wrapper) x)
  73. { this->Base::operator=((const Base &)x); return *this; }
  74. alloc_propagate_wrapper &operator=(BOOST_RV_REF(alloc_propagate_wrapper) x)
  75. { this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
  76. void swap(alloc_propagate_wrapper &x)
  77. { this->Base::swap(x); }
  78. };
  79. template<class T>
  80. struct get_real_stored_allocator
  81. {
  82. typedef typename T::stored_allocator_type type;
  83. };
  84. template<class Container>
  85. void test_propagate_allocator_allocator_arg();
  86. template<class Selector>
  87. bool test_propagate_allocator()
  88. {
  89. {
  90. typedef propagation_test_allocator<char, true, true, true, true> AlwaysPropagate;
  91. typedef alloc_propagate_wrapper<char, AlwaysPropagate, Selector> PropagateCont;
  92. typedef typename get_real_stored_allocator<typename PropagateCont::Base>::type StoredAllocator;
  93. {
  94. //////////////////////////////////////////
  95. //Test AlwaysPropagate allocator propagation
  96. //////////////////////////////////////////
  97. //default constructor
  98. StoredAllocator::reset_unique_id(111);
  99. PropagateCont c; //stored 112
  100. BOOST_TEST (c.get_stored_allocator().id_ == 112);
  101. BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
  102. BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
  103. BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
  104. BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
  105. BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
  106. }
  107. {
  108. //copy constructor
  109. StoredAllocator::reset_unique_id(222);
  110. PropagateCont c; //stored 223
  111. BOOST_TEST (c.get_stored_allocator().id_ == 223);
  112. //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler).
  113. //For allocators that copy in select_on_container_copy_construction, at least we must have a copy
  114. PropagateCont c2(c); //should propagate 223
  115. BOOST_TEST (c2.get_stored_allocator().id_ == 223);
  116. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 1);
  117. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
  118. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
  119. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  120. BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
  121. }
  122. {
  123. //move constructor
  124. StoredAllocator::reset_unique_id(333);
  125. PropagateCont c; //stored 334
  126. BOOST_TEST (c.get_stored_allocator().id_ == 334);
  127. PropagateCont c2(boost::move(c)); //should propagate 334
  128. BOOST_TEST (c2.get_stored_allocator().id_ == 334);
  129. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
  130. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ > 0);
  131. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
  132. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  133. BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
  134. }
  135. {
  136. //copy assign
  137. StoredAllocator::reset_unique_id(444);
  138. PropagateCont c; //stored 445
  139. BOOST_TEST (c.get_stored_allocator().id_ == 445);
  140. PropagateCont c2; //stored 446
  141. BOOST_TEST (c2.get_stored_allocator().id_ == 446);
  142. c2 = c; //should propagate 445
  143. BOOST_TEST (c2.get_stored_allocator().id_ == 445);
  144. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
  145. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
  146. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 1);
  147. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  148. BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
  149. }
  150. {
  151. //move assign
  152. StoredAllocator::reset_unique_id(555);
  153. PropagateCont c; //stored 556
  154. BOOST_TEST (c.get_stored_allocator().id_ == 556);
  155. PropagateCont c2; //stored 557
  156. BOOST_TEST (c2.get_stored_allocator().id_ == 557);
  157. c = boost::move(c2); //should propagate 557
  158. BOOST_TEST (c.get_stored_allocator().id_ == 557);
  159. BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
  160. BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
  161. BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
  162. BOOST_TEST (c.get_stored_allocator().assign_moves_ == 1);
  163. BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
  164. }
  165. {
  166. //swap
  167. StoredAllocator::reset_unique_id(666);
  168. PropagateCont c; //stored 667
  169. BOOST_TEST (c.get_stored_allocator().id_ == 667);
  170. PropagateCont c2; //stored 668
  171. BOOST_TEST (c2.get_stored_allocator().id_ == 668);
  172. c.swap(c2);
  173. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
  174. BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
  175. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
  176. BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
  177. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
  178. BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
  179. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  180. BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
  181. BOOST_TEST (c2.get_stored_allocator().swaps_ == 1);
  182. BOOST_TEST (c.get_stored_allocator().swaps_ == 1);
  183. }
  184. //And now allocator argument constructors
  185. test_propagate_allocator_allocator_arg<PropagateCont>();
  186. }
  187. //////////////////////////////////////////
  188. //Test NeverPropagate allocator propagation
  189. //////////////////////////////////////////
  190. {
  191. typedef propagation_test_allocator<char, false, false, false, false> NeverPropagate;
  192. typedef alloc_propagate_wrapper<char, NeverPropagate, Selector> NoPropagateCont;
  193. typedef typename get_real_stored_allocator<typename NoPropagateCont::Base>::type StoredAllocator;
  194. {
  195. //default constructor
  196. StoredAllocator::reset_unique_id(111);
  197. NoPropagateCont c; //stored 112
  198. BOOST_TEST (c.get_stored_allocator().id_ == 112);
  199. BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
  200. BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
  201. BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
  202. BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
  203. BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
  204. }
  205. {
  206. //copy constructor
  207. //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler)
  208. //For allocators that don't copy in select_on_container_copy_construction we must have a default
  209. //construction
  210. StoredAllocator::reset_unique_id(222);
  211. NoPropagateCont c; //stored 223
  212. BOOST_TEST (c.get_stored_allocator().id_ == 223);
  213. NoPropagateCont c2(c); //should NOT propagate 223
  214. BOOST_TEST (c2.get_stored_allocator().id_ == 224);
  215. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 0);
  216. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
  217. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
  218. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  219. BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
  220. }
  221. {
  222. //move constructor
  223. StoredAllocator::reset_unique_id(333);
  224. NoPropagateCont c; //stored 334
  225. BOOST_TEST (c.get_stored_allocator().id_ == 334);
  226. NoPropagateCont c2(boost::move(c)); // should NOT propagate 334
  227. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 0);
  228. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
  229. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
  230. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  231. BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
  232. }
  233. {
  234. //copy assign
  235. StoredAllocator::reset_unique_id(444);
  236. NoPropagateCont c; //stored 445
  237. NoPropagateCont c2; //stored 446
  238. c2 = c; // should NOT propagate 445
  239. BOOST_TEST (c2.get_stored_allocator().id_ == 446);
  240. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
  241. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
  242. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
  243. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  244. BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
  245. }
  246. {
  247. //move assign
  248. StoredAllocator::reset_unique_id(555);
  249. NoPropagateCont c; //stored 556
  250. NoPropagateCont c2; //stored 557
  251. c2 = c; // should NOT propagate 556
  252. BOOST_TEST (c2.get_stored_allocator().id_ == 557);
  253. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
  254. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
  255. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
  256. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  257. BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
  258. }
  259. {
  260. //swap
  261. StoredAllocator::reset_unique_id(666);
  262. NoPropagateCont c; //stored 667
  263. BOOST_TEST (c.get_stored_allocator().id_ == 667);
  264. NoPropagateCont c2; //stored 668
  265. BOOST_TEST (c2.get_stored_allocator().id_ == 668);
  266. c2.swap(c); // should NOT swap 667 and 668
  267. BOOST_TEST (c2.get_stored_allocator().id_ == 668);
  268. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
  269. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
  270. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
  271. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  272. BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
  273. BOOST_TEST (c.get_stored_allocator().id_ == 667);
  274. BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
  275. BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
  276. BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
  277. BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
  278. BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
  279. }
  280. //And now allocator argument constructors
  281. test_propagate_allocator_allocator_arg<NoPropagateCont>();
  282. }
  283. return report_errors() == 0;
  284. }
  285. template<class Container>
  286. void test_propagate_allocator_allocator_arg()
  287. {
  288. typedef typename Container::allocator_type allocator_type;
  289. typedef typename get_real_stored_allocator<typename Container::Base>::type StoredAllocator;
  290. { //The allocator must be always propagated
  291. //allocator constructor
  292. allocator_type::reset_unique_id(111);
  293. const allocator_type & a = allocator_type(); //stored 112
  294. Container c(a); //should propagate 112
  295. BOOST_TEST (c.get_stored_allocator().id_ == 112);
  296. BOOST_TEST (c.get_stored_allocator().ctr_copies_ > 0);
  297. BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
  298. BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
  299. BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
  300. BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
  301. }
  302. {
  303. //copy allocator constructor
  304. StoredAllocator::reset_unique_id(999);
  305. Container c;
  306. //stored_allocator_type could be the same type as allocator_type
  307. //so reset it again to get a predictable result
  308. allocator_type::reset_unique_id(222);
  309. Container c2(c, allocator_type()); //should propagate 223
  310. BOOST_TEST (c2.get_stored_allocator().id_ == 223);
  311. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
  312. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
  313. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
  314. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  315. BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
  316. }
  317. {
  318. //move allocator constructor
  319. StoredAllocator::reset_unique_id(999);
  320. Container c;
  321. //stored_allocator_type could be the same type as allocator_type
  322. //so reset it again to get a predictable result
  323. allocator_type::reset_unique_id(333);
  324. Container c2(boost::move(c), allocator_type()); //should propagate 334
  325. BOOST_TEST (c2.get_stored_allocator().id_ == 334);
  326. BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
  327. BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
  328. BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
  329. BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
  330. BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
  331. }
  332. }
  333. } //namespace test{
  334. } //namespace container {
  335. } //namespace boost{
  336. #include <boost/container/detail/config_end.hpp>
  337. #endif //#ifndef BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP