scoped_allocator_usage_test.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  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 <memory>
  12. #include <boost/move/utility_core.hpp>
  13. #include <boost/container/vector.hpp>
  14. #include <boost/container/deque.hpp>
  15. #include <boost/container/list.hpp>
  16. #include <boost/container/slist.hpp>
  17. #include <boost/container/stable_vector.hpp>
  18. #include <boost/container/small_vector.hpp>
  19. #include <boost/container/flat_map.hpp>
  20. #include <boost/container/flat_set.hpp>
  21. #include <boost/container/map.hpp>
  22. #include <boost/container/set.hpp>
  23. #include <boost/container/detail/mpl.hpp>
  24. #include <boost/container/scoped_allocator.hpp>
  25. template <typename Ty>
  26. class SimpleAllocator
  27. {
  28. public:
  29. typedef Ty value_type;
  30. explicit SimpleAllocator(int value)
  31. : m_state(value)
  32. {}
  33. template <typename T>
  34. SimpleAllocator(const SimpleAllocator<T> &other)
  35. : m_state(other.m_state)
  36. {}
  37. Ty* allocate(std::size_t n)
  38. {
  39. return m_allocator.allocate(n);
  40. }
  41. void deallocate(Ty* p, std::size_t n)
  42. {
  43. m_allocator.deallocate(p, n);
  44. }
  45. int get_value() const
  46. { return m_state; }
  47. private:
  48. int m_state;
  49. std::allocator<Ty> m_allocator;
  50. template <typename T> friend class SimpleAllocator;
  51. friend bool operator == (const SimpleAllocator &, const SimpleAllocator &)
  52. { return true; }
  53. friend bool operator != (const SimpleAllocator &, const SimpleAllocator &)
  54. { return false; }
  55. };
  56. class alloc_int
  57. {
  58. private: // Not copyable
  59. BOOST_MOVABLE_BUT_NOT_COPYABLE(alloc_int)
  60. public:
  61. typedef SimpleAllocator<int> allocator_type;
  62. alloc_int(BOOST_RV_REF(alloc_int)other)
  63. : m_value(other.m_value), m_allocator(boost::move(other.m_allocator))
  64. {
  65. other.m_value = -1;
  66. }
  67. alloc_int(BOOST_RV_REF(alloc_int)other, const allocator_type &allocator)
  68. : m_value(other.m_value), m_allocator(allocator)
  69. {
  70. other.m_value = -1;
  71. }
  72. alloc_int(int value, const allocator_type &allocator)
  73. : m_value(value), m_allocator(allocator)
  74. {}
  75. alloc_int & operator=(BOOST_RV_REF(alloc_int)other)
  76. {
  77. other.m_value = other.m_value;
  78. return *this;
  79. }
  80. int get_allocator_state() const
  81. { return m_allocator.get_value(); }
  82. int get_value() const
  83. { return m_value; }
  84. friend bool operator < (const alloc_int &l, const alloc_int &r)
  85. { return l.m_value < r.m_value; }
  86. friend bool operator == (const alloc_int &l, const alloc_int &r)
  87. { return l.m_value == r.m_value; }
  88. private:
  89. int m_value;
  90. allocator_type m_allocator;
  91. };
  92. using namespace ::boost::container;
  93. //general allocator
  94. typedef scoped_allocator_adaptor<SimpleAllocator<alloc_int> > AllocIntAllocator;
  95. //[multi]map/set
  96. typedef std::pair<const alloc_int, alloc_int> MapNode;
  97. typedef scoped_allocator_adaptor<SimpleAllocator<MapNode> > MapAllocator;
  98. typedef map<alloc_int, alloc_int, std::less<alloc_int>, MapAllocator> Map;
  99. typedef set<alloc_int, std::less<alloc_int>, AllocIntAllocator> Set;
  100. typedef multimap<alloc_int, alloc_int, std::less<alloc_int>, MapAllocator> MultiMap;
  101. typedef multiset<alloc_int, std::less<alloc_int>, AllocIntAllocator> MultiSet;
  102. //[multi]flat_map/set
  103. typedef std::pair<alloc_int, alloc_int> FlatMapNode;
  104. typedef scoped_allocator_adaptor<SimpleAllocator<FlatMapNode> > FlatMapAllocator;
  105. typedef flat_map<alloc_int, alloc_int, std::less<alloc_int>, FlatMapAllocator> FlatMap;
  106. typedef flat_set<alloc_int, std::less<alloc_int>, AllocIntAllocator> FlatSet;
  107. typedef flat_multimap<alloc_int, alloc_int, std::less<alloc_int>, FlatMapAllocator> FlatMultiMap;
  108. typedef flat_multiset<alloc_int, std::less<alloc_int>, AllocIntAllocator> FlatMultiSet;
  109. //vector, deque, list, slist, stable_vector.
  110. typedef vector<alloc_int, AllocIntAllocator> Vector;
  111. typedef deque<alloc_int, AllocIntAllocator> Deque;
  112. typedef list<alloc_int, AllocIntAllocator> List;
  113. typedef slist<alloc_int, AllocIntAllocator> Slist;
  114. typedef stable_vector<alloc_int, AllocIntAllocator> StableVector;
  115. typedef small_vector<alloc_int, 9, AllocIntAllocator> SmallVector;
  116. /////////
  117. //is_unique_assoc
  118. /////////
  119. template<class T>
  120. struct is_unique_assoc
  121. {
  122. static const bool value = false;
  123. };
  124. template<class Key, class T, class Compare, class Allocator>
  125. struct is_unique_assoc< map<Key, T, Compare, Allocator> >
  126. {
  127. static const bool value = true;
  128. };
  129. template<class Key, class T, class Compare, class Allocator>
  130. struct is_unique_assoc< flat_map<Key, T, Compare, Allocator> >
  131. {
  132. static const bool value = true;
  133. };
  134. template<class Key, class Compare, class Allocator>
  135. struct is_unique_assoc< set<Key, Compare, Allocator> >
  136. {
  137. static const bool value = true;
  138. };
  139. template<class Key, class Compare, class Allocator>
  140. struct is_unique_assoc< flat_set<Key, Compare, Allocator> >
  141. {
  142. static const bool value = true;
  143. };
  144. /////////
  145. //is_map
  146. /////////
  147. template<class T>
  148. struct is_map
  149. {
  150. static const bool value = false;
  151. };
  152. template<class Key, class T, class Compare, class Allocator>
  153. struct is_map< map<Key, T, Compare, Allocator> >
  154. {
  155. static const bool value = true;
  156. };
  157. template<class Key, class T, class Compare, class Allocator>
  158. struct is_map< flat_map<Key, T, Compare, Allocator> >
  159. {
  160. static const bool value = true;
  161. };
  162. template<class Key, class T, class Compare, class Allocator>
  163. struct is_map< multimap<Key, T, Compare, Allocator> >
  164. {
  165. static const bool value = true;
  166. };
  167. template<class Key, class T, class Compare, class Allocator>
  168. struct is_map< flat_multimap<Key, T, Compare, Allocator> >
  169. {
  170. static const bool value = true;
  171. };
  172. template<class T>
  173. struct is_set
  174. {
  175. static const bool value = false;
  176. };
  177. template<class Key, class Compare, class Allocator>
  178. struct is_set< set<Key, Compare, Allocator> >
  179. {
  180. static const bool value = true;
  181. };
  182. template<class Key, class Compare, class Allocator>
  183. struct is_set< flat_set<Key, Compare, Allocator> >
  184. {
  185. static const bool value = true;
  186. };
  187. template<class Key, class Compare, class Allocator>
  188. struct is_set< multiset<Key, Compare, Allocator> >
  189. {
  190. static const bool value = true;
  191. };
  192. template<class Key, class Compare, class Allocator>
  193. struct is_set< flat_multiset<Key, Compare, Allocator> >
  194. {
  195. static const bool value = true;
  196. };
  197. /////////
  198. //container_wrapper
  199. /////////
  200. //Try to define-allocator_aware requirements
  201. template< class Container
  202. , bool Assoc = is_set<Container>::value || is_map<Container>::value
  203. , bool UniqueAssoc = is_unique_assoc<Container>::value
  204. , bool Map = is_map<Container>::value
  205. >
  206. struct container_wrapper_inserter
  207. {
  208. typedef typename Container::const_iterator const_iterator;
  209. typedef typename Container::iterator iterator;
  210. template<class Arg>
  211. static iterator emplace(Container &c, const_iterator p, const Arg &arg)
  212. { return c.emplace(p, arg); }
  213. };
  214. template<class Container> //map
  215. struct container_wrapper_inserter<Container, true, true, true>
  216. {
  217. typedef typename Container::const_iterator const_iterator;
  218. typedef typename Container::iterator iterator;
  219. template<class Arg>
  220. static iterator emplace(Container &c, const_iterator, const Arg &arg)
  221. { return c.emplace(arg, arg).first; }
  222. };
  223. template<class Container> //set
  224. struct container_wrapper_inserter<Container, true, true, false>
  225. {
  226. typedef typename Container::const_iterator const_iterator;
  227. typedef typename Container::iterator iterator;
  228. template<class Arg>
  229. static iterator emplace(Container &c, const_iterator, const Arg &arg)
  230. { return c.emplace(arg).first; }
  231. };
  232. template<class Container> //multimap
  233. struct container_wrapper_inserter<Container, true, false, true>
  234. {
  235. typedef typename Container::const_iterator const_iterator;
  236. typedef typename Container::iterator iterator;
  237. template<class Arg>
  238. static iterator emplace(Container &c, const_iterator, const Arg &arg)
  239. { return c.emplace(arg, arg); }
  240. };
  241. //multiset
  242. template<class Container> //multimap
  243. struct container_wrapper_inserter<Container, true, false, false>
  244. {
  245. typedef typename Container::const_iterator const_iterator;
  246. typedef typename Container::iterator iterator;
  247. template<class Arg>
  248. static iterator emplace(Container &c, const_iterator, const Arg &arg)
  249. { return c.emplace(arg); }
  250. };
  251. template< class Container>
  252. struct container_wrapper
  253. : public Container
  254. {
  255. private:
  256. BOOST_COPYABLE_AND_MOVABLE(container_wrapper)
  257. public:
  258. typedef typename Container::allocator_type allocator_type;
  259. typedef typename Container::const_iterator const_iterator;
  260. typedef typename Container::iterator iterator;
  261. container_wrapper(const allocator_type &a)
  262. : Container(a)
  263. {}
  264. container_wrapper(BOOST_RV_REF(container_wrapper) o, const allocator_type &a)
  265. : Container(BOOST_MOVE_BASE(Container, o), a)
  266. {}
  267. container_wrapper(const container_wrapper &o, const allocator_type &a)
  268. : Container(o, a)
  269. {}
  270. template<class Arg>
  271. iterator emplace(const_iterator p, const Arg &arg)
  272. { return container_wrapper_inserter<Container>::emplace(*this, p, arg); }
  273. };
  274. bool test_value_and_state_equals(const alloc_int &r, int value, int state)
  275. { return r.get_value() == value && r.get_allocator_state() == state; }
  276. template<class F, class S>
  277. bool test_value_and_state_equals(const dtl::pair<F, S> &p, int value, int state)
  278. { return test_value_and_state_equals(p.first, value, state) && test_alloc_state_equals(p.second, value, state); }
  279. template<class F, class S>
  280. bool test_value_and_state_equals(const std::pair<F, S> &p, int value, int state)
  281. { return test_value_and_state_equals(p.first, value, state) && test_value_and_state_equals(p.second, value, state); }
  282. template<class Container>
  283. bool one_level_allocator_propagation_test()
  284. {
  285. typedef container_wrapper<Container> ContainerWrapper;
  286. typedef typename ContainerWrapper::iterator iterator;
  287. typedef typename ContainerWrapper::allocator_type allocator_type;
  288. typedef typename ContainerWrapper::value_type value_type;
  289. {
  290. allocator_type al(SimpleAllocator<value_type>(5));
  291. ContainerWrapper c(al);
  292. c.clear();
  293. iterator it = c.emplace(c.cbegin(), 42);
  294. if(!test_value_and_state_equals(*it, 42, 5))
  295. return false;
  296. }
  297. {
  298. allocator_type al(SimpleAllocator<value_type>(4));
  299. ContainerWrapper c2(al);
  300. ContainerWrapper c(::boost::move(c2), allocator_type(SimpleAllocator<value_type>(5)));
  301. c.clear();
  302. iterator it = c.emplace(c.cbegin(), 42);
  303. if(!test_value_and_state_equals(*it, 42, 5))
  304. return false;
  305. }/*
  306. {
  307. ContainerWrapper c2(allocator_type(SimpleAllocator<value_type>(3)));
  308. ContainerWrapper c(c2, allocator_type(SimpleAllocator<value_type>(5)));
  309. c.clear();
  310. iterator it = c.emplace(c.cbegin(), 42);
  311. if(!test_value_and_state_equals(*it, 42, 5))
  312. return false;
  313. }*/
  314. return true;
  315. }
  316. int main()
  317. {
  318. //unique assoc
  319. if(!one_level_allocator_propagation_test<FlatMap>())
  320. return 1;
  321. if(!one_level_allocator_propagation_test<Map>())
  322. return 1;
  323. if(!one_level_allocator_propagation_test<FlatSet>())
  324. return 1;
  325. if(!one_level_allocator_propagation_test<Set>())
  326. return 1;
  327. //multi assoc
  328. if(!one_level_allocator_propagation_test<FlatMultiMap>())
  329. return 1;
  330. if(!one_level_allocator_propagation_test<MultiMap>())
  331. return 1;
  332. if(!one_level_allocator_propagation_test<FlatMultiSet>())
  333. return 1;
  334. if(!one_level_allocator_propagation_test<MultiSet>())
  335. return 1;
  336. //sequence containers
  337. if(!one_level_allocator_propagation_test<Vector>())
  338. return 1;
  339. if(!one_level_allocator_propagation_test<Deque>())
  340. return 1;
  341. if(!one_level_allocator_propagation_test<List>())
  342. return 1;
  343. if(!one_level_allocator_propagation_test<Slist>())
  344. return 1;
  345. if(!one_level_allocator_propagation_test<StableVector>())
  346. return 1;
  347. if(!one_level_allocator_propagation_test<SmallVector>())
  348. return 1;
  349. return 0;
  350. }
  351. #include <boost/container/detail/config_end.hpp>