allocator_traits_test.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2011-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 <cstddef>
  12. #include <boost/container/allocator_traits.hpp>
  13. #include <boost/static_assert.hpp>
  14. #include <boost/container/detail/type_traits.hpp>
  15. #include <boost/container/detail/function_detector.hpp>
  16. #include <boost/move/utility_core.hpp>
  17. #include <memory>
  18. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  19. #include <boost/move/detail/fwd_macros.hpp>
  20. #endif
  21. #include <boost/core/lightweight_test.hpp>
  22. template<class T>
  23. class SimpleAllocator
  24. {
  25. public:
  26. bool allocate_called_;
  27. bool deallocate_called_;
  28. typedef boost::container::dtl::
  29. true_type is_always_equal;
  30. typedef T value_type;
  31. template <class U>
  32. SimpleAllocator(SimpleAllocator<U>)
  33. : allocate_called_(false)
  34. , deallocate_called_(false)
  35. {}
  36. SimpleAllocator()
  37. : allocate_called_(false)
  38. , deallocate_called_(false)
  39. {}
  40. T* allocate(std::size_t)
  41. { allocate_called_ = true; return 0; }
  42. void deallocate(T*, std::size_t)
  43. { deallocate_called_ = true; }
  44. bool allocate_called() const
  45. { return allocate_called_; }
  46. bool deallocate_called() const
  47. { return deallocate_called_; }
  48. friend bool operator==(const SimpleAllocator &, const SimpleAllocator &)
  49. { return true; }
  50. friend bool operator!=(const SimpleAllocator &, const SimpleAllocator &)
  51. { return false; }
  52. };
  53. template<class T>
  54. class SimpleSmartPtr
  55. {
  56. void unspecified_bool_type_func() const {}
  57. typedef void (SimpleSmartPtr::*unspecified_bool_type)() const;
  58. public:
  59. typedef T* pointer;
  60. explicit SimpleSmartPtr(pointer p = 0)
  61. : ptr_(p)
  62. {}
  63. SimpleSmartPtr(const SimpleSmartPtr &c)
  64. { this->ptr_ = c.ptr_; }
  65. SimpleSmartPtr & operator=(const SimpleSmartPtr &c)
  66. { this->ptr_ = c.ptr_; }
  67. operator unspecified_bool_type() const
  68. { return ptr_? &SimpleSmartPtr::unspecified_bool_type_func : 0; }
  69. private:
  70. T *ptr_;
  71. };
  72. template<class T>
  73. class ComplexAllocator
  74. {
  75. public:
  76. bool allocate_called_;
  77. bool deallocate_called_;
  78. bool allocate_hint_called_;
  79. bool destroy_called_;
  80. mutable bool max_size_called_;
  81. mutable bool select_on_container_copy_construction_called_;
  82. bool construct_called_;
  83. mutable bool storage_is_unpropagable_;
  84. typedef T value_type;
  85. typedef SimpleSmartPtr<T> pointer;
  86. typedef SimpleSmartPtr<const T> const_pointer;
  87. typedef typename ::boost::container::
  88. dtl::unvoid_ref<T>::type reference;
  89. typedef typename ::boost::container::
  90. dtl::unvoid_ref<const T>::type const_reference;
  91. typedef SimpleSmartPtr<void> void_pointer;
  92. typedef SimpleSmartPtr<const void> const_void_pointer;
  93. typedef signed short difference_type;
  94. typedef unsigned short size_type;
  95. typedef boost::container::dtl::
  96. true_type propagate_on_container_copy_assignment;
  97. typedef boost::container::dtl::
  98. true_type propagate_on_container_move_assignment;
  99. typedef boost::container::dtl::
  100. true_type propagate_on_container_swap;
  101. typedef boost::container::dtl::
  102. true_type is_partially_propagable;
  103. ComplexAllocator()
  104. : allocate_called_(false)
  105. , deallocate_called_(false)
  106. , allocate_hint_called_(false)
  107. , destroy_called_(false)
  108. , max_size_called_(false)
  109. , select_on_container_copy_construction_called_(false)
  110. , construct_called_(false)
  111. {}
  112. pointer allocate(size_type)
  113. { allocate_called_ = true; return pointer(); }
  114. void deallocate(pointer, size_type)
  115. { deallocate_called_ = true; }
  116. //optional
  117. ComplexAllocator select_on_container_copy_construction() const
  118. { select_on_container_copy_construction_called_ = true; return *this; }
  119. pointer allocate(size_type n, const const_void_pointer &)
  120. { allocate_hint_called_ = true; return allocate(n); }
  121. template<class U>
  122. void destroy(U*)
  123. { destroy_called_ = true; }
  124. size_type max_size() const
  125. { max_size_called_ = true; return size_type(size_type(0)-1); }
  126. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  127. #define BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL(N)\
  128. \
  129. template< class U BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
  130. void construct(U *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
  131. { construct_called_ = true; ::new(p) U ( BOOST_MOVE_FWD##N ); }\
  132. //
  133. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL)
  134. #undef BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL
  135. #else
  136. template< class U, class ...Args>
  137. void construct(U *p, BOOST_FWD_REF(Args) ...args)
  138. { construct_called_ = true; ::new(p) U( ::boost::forward<Args>(args)...); }
  139. #endif
  140. template<class U>
  141. void construct(U *p, boost::container::default_init_t)
  142. { construct_called_ = true; ::new(p)U; }
  143. bool storage_is_unpropagable(pointer p) const
  144. { storage_is_unpropagable_ = true; return !p; }
  145. //getters
  146. bool allocate_called() const
  147. { return allocate_called_; }
  148. bool deallocate_called() const
  149. { return deallocate_called_; }
  150. bool allocate_hint_called() const
  151. { return allocate_hint_called_; }
  152. bool destroy_called() const
  153. { return destroy_called_; }
  154. bool max_size_called() const
  155. { return max_size_called_; }
  156. bool select_on_container_copy_construction_called() const
  157. { return select_on_container_copy_construction_called_; }
  158. bool construct_called() const
  159. { return construct_called_; }
  160. bool storage_is_unpropagable_called() const
  161. { return storage_is_unpropagable_; }
  162. };
  163. class copymovable
  164. {
  165. BOOST_COPYABLE_AND_MOVABLE(copymovable)
  166. public:
  167. bool copymoveconstructed_;
  168. bool moved_;
  169. copymovable(int, int, int)
  170. : copymoveconstructed_(false), moved_(false)
  171. {}
  172. copymovable()
  173. : copymoveconstructed_(false), moved_(false)
  174. {}
  175. copymovable(const copymovable &)
  176. : copymoveconstructed_(true), moved_(false)
  177. {}
  178. copymovable(BOOST_RV_REF(copymovable))
  179. : copymoveconstructed_(true), moved_(true)
  180. {}
  181. copymovable & operator=(BOOST_COPY_ASSIGN_REF(copymovable) ){ return *this; }
  182. copymovable & operator=(BOOST_RV_REF(copymovable) ){ return *this; }
  183. bool copymoveconstructed() const
  184. { return copymoveconstructed_; }
  185. bool moved() const
  186. { return moved_; }
  187. };
  188. void test_void_allocator()
  189. {
  190. boost::container::allocator_traits<std::allocator<void> > stdtraits; (void)stdtraits;
  191. boost::container::allocator_traits<SimpleAllocator<void> > simtraits; (void)simtraits;
  192. boost::container::allocator_traits<ComplexAllocator<void> > comtraits; (void)comtraits;
  193. }
  194. int main()
  195. {
  196. using namespace boost::container::dtl;
  197. test_void_allocator();
  198. //SimpleAllocator
  199. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  200. < SimpleAllocator<int> >::value_type, int>::value ));
  201. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  202. < SimpleAllocator<int> >::pointer, int*>::value ));
  203. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  204. < SimpleAllocator<int> >::const_pointer, const int*>::value ));
  205. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  206. < SimpleAllocator<int> >::void_pointer, void*>::value ));
  207. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  208. < SimpleAllocator<int> >::const_void_pointer, const void*>::value ));
  209. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  210. < SimpleAllocator<int> >::difference_type, std::ptrdiff_t>::value ));
  211. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  212. < SimpleAllocator<int> >::size_type, std::size_t>::value ));
  213. BOOST_STATIC_ASSERT(( boost::container::allocator_traits
  214. < SimpleAllocator<int> >::propagate_on_container_copy_assignment::value == false ));
  215. BOOST_STATIC_ASSERT(( boost::container::allocator_traits
  216. < SimpleAllocator<int> >::propagate_on_container_move_assignment::value == false ));
  217. BOOST_STATIC_ASSERT(( boost::container::allocator_traits
  218. < SimpleAllocator<int> >::propagate_on_container_swap::value == false ));
  219. BOOST_STATIC_ASSERT(( boost::container::allocator_traits
  220. < SimpleAllocator<int> >::is_always_equal::value == true ));
  221. BOOST_STATIC_ASSERT(( boost::container::allocator_traits
  222. < SimpleAllocator<int> >::is_partially_propagable::value == false ));
  223. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  224. < SimpleAllocator<int> >::rebind_traits<double>::allocator_type
  225. , SimpleAllocator<double> >::value ));
  226. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  227. < SimpleAllocator<int> >::rebind_alloc<double>::value_type
  228. , double >::value ));
  229. //ComplexAllocator
  230. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  231. < ComplexAllocator<int> >::value_type, int>::value ));
  232. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  233. < ComplexAllocator<int> >::pointer, SimpleSmartPtr<int> >::value ));
  234. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  235. < ComplexAllocator<int> >::const_pointer, SimpleSmartPtr<const int> >::value ));
  236. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  237. < ComplexAllocator<int> >::void_pointer, SimpleSmartPtr<void> >::value ));
  238. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  239. < ComplexAllocator<int> >::const_void_pointer, SimpleSmartPtr<const void> >::value ));
  240. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  241. < ComplexAllocator<int> >::difference_type, signed short>::value ));
  242. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  243. < ComplexAllocator<int> >::size_type, unsigned short>::value ));
  244. BOOST_STATIC_ASSERT(( boost::container::allocator_traits
  245. < ComplexAllocator<int> >::propagate_on_container_copy_assignment::value == true ));
  246. BOOST_STATIC_ASSERT(( boost::container::allocator_traits
  247. < ComplexAllocator<int> >::propagate_on_container_move_assignment::value == true ));
  248. BOOST_STATIC_ASSERT(( boost::container::allocator_traits
  249. < ComplexAllocator<int> >::propagate_on_container_swap::value == true ));
  250. BOOST_STATIC_ASSERT(( boost::container::allocator_traits
  251. < ComplexAllocator<int> >::is_always_equal::value == false ));
  252. BOOST_STATIC_ASSERT(( boost::container::allocator_traits
  253. < ComplexAllocator<int> >::is_partially_propagable::value == true ));
  254. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  255. < ComplexAllocator<int> >::rebind_traits<double>::allocator_type
  256. , ComplexAllocator<double> >::value ));
  257. BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
  258. < ComplexAllocator<int> >::rebind_alloc<double>::value_type
  259. , double >::value ));
  260. typedef ComplexAllocator<int> CAlloc;
  261. typedef SimpleAllocator<int> SAlloc;
  262. typedef boost::container::allocator_traits<CAlloc> CAllocTraits;
  263. typedef boost::container::allocator_traits<SAlloc> SAllocTraits;
  264. CAlloc c_alloc;
  265. SAlloc s_alloc;
  266. //allocate
  267. CAllocTraits::allocate(c_alloc, 1);
  268. BOOST_TEST(c_alloc.allocate_called());
  269. SAllocTraits::allocate(s_alloc, 1);
  270. BOOST_TEST(s_alloc.allocate_called());
  271. //deallocate
  272. CAllocTraits::deallocate(c_alloc, CAllocTraits::pointer(), 1);
  273. BOOST_TEST(c_alloc.deallocate_called());
  274. SAllocTraits::deallocate(s_alloc, SAllocTraits::pointer(), 1);
  275. BOOST_TEST(s_alloc.deallocate_called());
  276. //allocate with hint
  277. CAllocTraits::allocate(c_alloc, 1, CAllocTraits::const_void_pointer());
  278. BOOST_TEST(c_alloc.allocate_hint_called());
  279. s_alloc.allocate_called_ = false;
  280. SAllocTraits::allocate(s_alloc, 1, SAllocTraits::const_void_pointer());
  281. BOOST_TEST(s_alloc.allocate_called());
  282. //destroy
  283. float dummy;
  284. CAllocTraits::destroy(c_alloc, &dummy);
  285. BOOST_TEST(c_alloc.destroy_called());
  286. SAllocTraits::destroy(s_alloc, &dummy);
  287. //max_size
  288. CAllocTraits::max_size(c_alloc);
  289. BOOST_TEST(c_alloc.max_size_called());
  290. BOOST_TEST(SAllocTraits::size_type(-1)/sizeof(SAllocTraits::value_type) == SAllocTraits::max_size(s_alloc));
  291. //select_on_container_copy_construction
  292. CAllocTraits::select_on_container_copy_construction(c_alloc);
  293. BOOST_TEST(c_alloc.select_on_container_copy_construction_called());
  294. SAllocTraits::select_on_container_copy_construction(s_alloc);
  295. //construct
  296. {
  297. copymovable c;
  298. c.copymoveconstructed_ = true;
  299. c.copymoveconstructed_ = true;
  300. CAllocTraits::construct(c_alloc, &c);
  301. BOOST_TEST(c_alloc.construct_called() && !c.copymoveconstructed() && !c.moved());
  302. }
  303. {
  304. int i = 5;
  305. CAllocTraits::construct(c_alloc, &i, boost::container::default_init);
  306. BOOST_TEST(c_alloc.construct_called() && i == 5);
  307. }
  308. {
  309. copymovable c;
  310. copymovable c2;
  311. CAllocTraits::construct(c_alloc, &c, c2);
  312. BOOST_TEST(c_alloc.construct_called() && c.copymoveconstructed() && !c.moved());
  313. }
  314. {
  315. copymovable c;
  316. copymovable c2;
  317. CAllocTraits::construct(c_alloc, &c, ::boost::move(c2));
  318. BOOST_TEST(c_alloc.construct_called() && c.copymoveconstructed() && c.moved());
  319. }
  320. {
  321. copymovable c;
  322. c.copymoveconstructed_ = true;
  323. c.copymoveconstructed_ = true;
  324. SAllocTraits::construct(s_alloc, &c);
  325. BOOST_TEST(!c.copymoveconstructed() && !c.moved());
  326. }
  327. {
  328. int i = 4;
  329. SAllocTraits::construct(s_alloc, &i, boost::container::default_init);
  330. BOOST_TEST(i == 4);
  331. }
  332. {
  333. copymovable c;
  334. copymovable c2;
  335. SAllocTraits::construct(s_alloc, &c, c2);
  336. BOOST_TEST(c.copymoveconstructed() && !c.moved());
  337. }
  338. {
  339. copymovable c;
  340. copymovable c2;
  341. SAllocTraits::construct(s_alloc, &c, ::boost::move(c2));
  342. BOOST_TEST(c.copymoveconstructed() && c.moved());
  343. }
  344. {
  345. copymovable c;
  346. CAllocTraits::construct(c_alloc, &c, 0, 1, 2);
  347. BOOST_TEST(c_alloc.construct_called() && !c.copymoveconstructed() && !c.moved());
  348. }
  349. {
  350. copymovable c;
  351. copymovable c2;
  352. SAllocTraits::construct(s_alloc, &c, 0, 1, 2);
  353. BOOST_TEST(!c.copymoveconstructed() && !c.moved());
  354. }
  355. //storage_is_unpropagable
  356. {
  357. SAlloc s_alloc2;
  358. BOOST_TEST(!SAllocTraits::storage_is_unpropagable(s_alloc, SAllocTraits::pointer()));
  359. }
  360. {
  361. {
  362. CAlloc c_alloc2;
  363. CAlloc::value_type v;
  364. BOOST_TEST(!CAllocTraits::storage_is_unpropagable(c_alloc, CAllocTraits::pointer(&v)));
  365. BOOST_TEST(c_alloc.storage_is_unpropagable_called());
  366. }
  367. {
  368. CAlloc c_alloc2;
  369. BOOST_TEST( CAllocTraits::storage_is_unpropagable(c_alloc2, CAllocTraits::pointer()));
  370. BOOST_TEST(c_alloc2.storage_is_unpropagable_called());
  371. }
  372. }
  373. return ::boost::report_errors();
  374. }
  375. #include <boost/container/detail/config_end.hpp>