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 <memory>
11
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
25#include <boost/container/scoped_allocator.hpp>
26
27template <typename Ty>
28class SimpleAllocator
29{
30public:
31 typedef Ty value_type;
32
33 explicit SimpleAllocator(int value)
34 : m_state(value)
35 {}
36
37 template <typename T>
38 SimpleAllocator(const SimpleAllocator<T> &other)
39 : m_state(other.m_state)
40 {}
41
42 Ty* allocate(std::size_t n)
43 {
44 return m_allocator.allocate(n);
45 }
46
47 void deallocate(Ty* p, std::size_t n)
48 {
49 m_allocator.deallocate(p, n);
50 }
51
52 int get_value() const
53 { return m_state; }
54
55 private:
56 int m_state;
57 std::allocator<Ty> m_allocator;
58
59 template <typename T> friend class SimpleAllocator;
60
61 friend bool operator == (const SimpleAllocator &a, const SimpleAllocator &b)
62 { return a.m_state == b.m_state; }
63
64 friend bool operator != (const SimpleAllocator &a, const SimpleAllocator &b)
65 { return a.m_state != b.m_state; }
66};
67
68class alloc_int
69{
70 private: // Not copyable
71
72 BOOST_COPYABLE_AND_MOVABLE(alloc_int)
73
74 public:
75 typedef SimpleAllocator<int> allocator_type;
76
77 alloc_int(BOOST_RV_REF(alloc_int)other)
78 : m_value(other.m_value), m_allocator(boost::move(t&: other.m_allocator))
79 {
80 other.m_value = -1;
81 }
82
83 alloc_int(BOOST_RV_REF(alloc_int)other, const allocator_type &allocator)
84 : m_value(other.m_value), m_allocator(allocator)
85 {
86 other.m_value = -1;
87 }
88
89 alloc_int(const alloc_int &other)
90 : m_value(other.m_value), m_allocator(boost::move(t: other.m_allocator))
91 {
92 }
93
94 alloc_int(const alloc_int &other, const allocator_type &allocator)
95 : m_value(other.m_value), m_allocator(allocator)
96 {
97 }
98
99 alloc_int(int value, const allocator_type &allocator)
100 : m_value(value), m_allocator(allocator)
101 {}
102
103 alloc_int & operator=(BOOST_RV_REF(alloc_int)other)
104 {
105 m_value = other.m_value;
106 other.m_value = -1;
107 return *this;
108 }
109
110 alloc_int & operator=(const alloc_int &other)
111 {
112 m_value = other.m_value;
113 return *this;
114 }
115
116 int get_allocator_state() const
117 { return m_allocator.get_value(); }
118
119 int get_value() const
120 { return m_value; }
121
122 friend bool operator < (const alloc_int &l, const alloc_int &r)
123 { return l.m_value < r.m_value; }
124
125 friend bool operator == (const alloc_int &l, const alloc_int &r)
126 { return l.m_value == r.m_value; }
127
128 private:
129 int m_value;
130 allocator_type m_allocator;
131};
132
133using namespace ::boost::container;
134
135//general allocator
136typedef scoped_allocator_adaptor<SimpleAllocator<alloc_int> > AllocIntAllocator;
137
138//[multi]map/set
139typedef std::pair<const alloc_int, alloc_int> MapNode;
140typedef scoped_allocator_adaptor<SimpleAllocator<MapNode> > MapAllocator;
141typedef map<alloc_int, alloc_int, std::less<alloc_int>, MapAllocator> Map;
142typedef set<alloc_int, std::less<alloc_int>, AllocIntAllocator> Set;
143typedef multimap<alloc_int, alloc_int, std::less<alloc_int>, MapAllocator> MultiMap;
144typedef multiset<alloc_int, std::less<alloc_int>, AllocIntAllocator> MultiSet;
145
146//[multi]flat_map/set
147typedef std::pair<alloc_int, alloc_int> FlatMapNode;
148typedef scoped_allocator_adaptor<SimpleAllocator<FlatMapNode> > FlatMapAllocator;
149typedef flat_map<alloc_int, alloc_int, std::less<alloc_int>, FlatMapAllocator> FlatMap;
150typedef flat_set<alloc_int, std::less<alloc_int>, AllocIntAllocator> FlatSet;
151typedef flat_multimap<alloc_int, alloc_int, std::less<alloc_int>, FlatMapAllocator> FlatMultiMap;
152typedef flat_multiset<alloc_int, std::less<alloc_int>, AllocIntAllocator> FlatMultiSet;
153
154//vector, deque, list, slist, stable_vector.
155typedef vector<alloc_int, AllocIntAllocator> Vector;
156typedef deque<alloc_int, AllocIntAllocator> Deque;
157typedef list<alloc_int, AllocIntAllocator> List;
158typedef slist<alloc_int, AllocIntAllocator> Slist;
159typedef stable_vector<alloc_int, AllocIntAllocator> StableVector;
160typedef small_vector<alloc_int, 9, AllocIntAllocator> SmallVector;
161
162/////////
163//is_unique_assoc
164/////////
165
166template<class T>
167struct is_unique_assoc
168{
169 static const bool value = false;
170};
171
172template<class Key, class T, class Compare, class Allocator>
173struct is_unique_assoc< map<Key, T, Compare, Allocator> >
174{
175 static const bool value = true;
176};
177
178template<class Key, class T, class Compare, class Allocator>
179struct is_unique_assoc< flat_map<Key, T, Compare, Allocator> >
180{
181 static const bool value = true;
182};
183
184template<class Key, class Compare, class Allocator>
185struct is_unique_assoc< set<Key, Compare, Allocator> >
186{
187 static const bool value = true;
188};
189
190template<class Key, class Compare, class Allocator>
191struct is_unique_assoc< flat_set<Key, Compare, Allocator> >
192{
193 static const bool value = true;
194};
195
196
197/////////
198//is_map
199/////////
200
201template<class T>
202struct is_map
203{
204 static const bool value = false;
205};
206
207template<class Key, class T, class Compare, class Allocator>
208struct is_map< map<Key, T, Compare, Allocator> >
209{
210 static const bool value = true;
211};
212
213template<class Key, class T, class Compare, class Allocator>
214struct is_map< flat_map<Key, T, Compare, Allocator> >
215{
216 static const bool value = true;
217};
218
219template<class Key, class T, class Compare, class Allocator>
220struct is_map< multimap<Key, T, Compare, Allocator> >
221{
222 static const bool value = true;
223};
224
225template<class Key, class T, class Compare, class Allocator>
226struct is_map< flat_multimap<Key, T, Compare, Allocator> >
227{
228 static const bool value = true;
229};
230
231template<class T>
232struct is_set
233{
234 static const bool value = false;
235};
236
237template<class Key, class Compare, class Allocator>
238struct is_set< set<Key, Compare, Allocator> >
239{
240 static const bool value = true;
241};
242
243template<class Key, class Compare, class Allocator>
244struct is_set< flat_set<Key, Compare, Allocator> >
245{
246 static const bool value = true;
247};
248
249template<class Key, class Compare, class Allocator>
250struct is_set< multiset<Key, Compare, Allocator> >
251{
252 static const bool value = true;
253};
254
255template<class Key, class Compare, class Allocator>
256struct is_set< flat_multiset<Key, Compare, Allocator> >
257{
258 static const bool value = true;
259};
260
261/////////
262//container_wrapper
263/////////
264
265//Try to define-allocator_aware requirements
266template< class Container
267 , bool Assoc = is_set<Container>::value || is_map<Container>::value
268 , bool UniqueAssoc = is_unique_assoc<Container>::value
269 , bool Map = is_map<Container>::value
270 >
271struct container_wrapper_inserter
272{
273 typedef typename Container::const_iterator const_iterator;
274 typedef typename Container::iterator iterator;
275
276 template<class Arg>
277 static iterator emplace(Container &c, const_iterator p, const Arg &arg)
278 { return c.emplace(p, arg); }
279};
280
281template<class Container> //map
282struct container_wrapper_inserter<Container, true, true, true>
283{
284 typedef typename Container::const_iterator const_iterator;
285 typedef typename Container::iterator iterator;
286
287 template<class Arg>
288 static iterator emplace(Container &c, const_iterator, const Arg &arg)
289 { return c.emplace(arg, arg).first; }
290};
291
292template<class Container> //set
293struct container_wrapper_inserter<Container, true, true, false>
294{
295 typedef typename Container::const_iterator const_iterator;
296 typedef typename Container::iterator iterator;
297
298 template<class Arg>
299 static iterator emplace(Container &c, const_iterator, const Arg &arg)
300 { return c.emplace(arg).first; }
301};
302
303template<class Container> //multimap
304struct container_wrapper_inserter<Container, true, false, true>
305{
306 typedef typename Container::const_iterator const_iterator;
307 typedef typename Container::iterator iterator;
308
309 template<class Arg>
310 static iterator emplace(Container &c, const_iterator, const Arg &arg)
311 { return c.emplace(arg, arg); }
312};
313
314//multiset
315template<class Container> //multimap
316struct container_wrapper_inserter<Container, true, false, false>
317{
318 typedef typename Container::const_iterator const_iterator;
319 typedef typename Container::iterator iterator;
320
321 template<class Arg>
322 static iterator emplace(Container &c, const_iterator, const Arg &arg)
323 { return c.emplace(arg); }
324};
325
326template< class Container>
327struct container_wrapper
328 : public Container
329{
330 private:
331 BOOST_COPYABLE_AND_MOVABLE(container_wrapper)
332
333 public:
334 typedef typename Container::allocator_type allocator_type;
335 typedef typename Container::const_iterator const_iterator;
336 typedef typename Container::iterator iterator;
337
338 container_wrapper(const allocator_type &a)
339 : Container(a)
340 {}
341
342 container_wrapper(BOOST_RV_REF(container_wrapper) o, const allocator_type &a)
343 : Container(BOOST_MOVE_BASE(Container, o), a)
344 {}
345
346 container_wrapper(const container_wrapper &o, const allocator_type &a)
347 : Container(o, a)
348 {}
349
350 template<class Arg>
351 iterator emplace(const_iterator p, const Arg &arg)
352 { return container_wrapper_inserter<Container>::emplace(*this, p, arg); }
353};
354
355
356bool test_value_and_state_equals(const alloc_int &r, int value, int state)
357{ return r.get_value() == value && r.get_allocator_state() == state; }
358
359template<class F, class S>
360bool test_value_and_state_equals(const dtl::pair<F, S> &p, int value, int state)
361{ return test_value_and_state_equals(p.first, value, state) && test_alloc_state_equals(p.second, value, state); }
362
363template<class F, class S>
364bool test_value_and_state_equals(const std::pair<F, S> &p, int value, int state)
365{ return test_value_and_state_equals(p.first, value, state) && test_value_and_state_equals(p.second, value, state); }
366
367template<class Container>
368bool one_level_allocator_propagation_test()
369{
370 typedef container_wrapper<Container> ContainerWrapper;
371 typedef typename ContainerWrapper::iterator iterator;
372 typedef typename ContainerWrapper::allocator_type allocator_type;
373 typedef typename ContainerWrapper::value_type value_type;
374 {
375 allocator_type al(SimpleAllocator<value_type>(5));
376 ContainerWrapper c(al);
377
378 c.clear();
379 iterator it = c.emplace(c.cbegin(), 42);
380
381 if(!test_value_and_state_equals(*it, 42, 5))
382 return false;
383 }
384 {
385 allocator_type al(SimpleAllocator<value_type>(4));
386 ContainerWrapper c2(al);
387 {
388 iterator it = c2.emplace(c2.cbegin(), 41);
389 if(!test_value_and_state_equals(*it, 41, 4))
390 return false;
391 }
392
393 ContainerWrapper c(::boost::move(c2), allocator_type(SimpleAllocator<value_type>(5)));
394
395 if(!test_value_and_state_equals(*c.begin(), 41, 5))
396 return false;
397
398 {
399 c.clear();
400 iterator it = c.emplace(c.cbegin(), 42);
401
402 if(!test_value_and_state_equals(*it, 42, 5))
403 return false;
404 }
405 }
406 {
407 allocator_type al(SimpleAllocator<value_type>(4));
408 ContainerWrapper c2(al);
409 {
410 iterator it = c2.emplace(c2.cbegin(), 41);
411 if(!test_value_and_state_equals(*it, 41, 4))
412 return false;
413 }
414
415 ContainerWrapper c(c2, allocator_type(SimpleAllocator<value_type>(5)));
416
417 if(!test_value_and_state_equals(*c.begin(), 41, 5))
418 return false;
419
420 {
421 c.clear();
422 iterator it = c.emplace(c.cbegin(), 42);
423
424 if(!test_value_and_state_equals(*it, 42, 5))
425 return false;
426 }
427 }
428 return true;
429}
430
431int main()
432{
433 //unique assoc
434 if(!one_level_allocator_propagation_test<FlatMap>())
435 return 1;
436 if(!one_level_allocator_propagation_test<Map>())
437 return 1;
438 if(!one_level_allocator_propagation_test<FlatSet>())
439 return 1;
440 if(!one_level_allocator_propagation_test<Set>())
441 return 1;
442 //multi assoc
443 if(!one_level_allocator_propagation_test<FlatMultiMap>())
444 return 1;
445 if(!one_level_allocator_propagation_test<MultiMap>())
446 return 1;
447 if(!one_level_allocator_propagation_test<FlatMultiSet>())
448 return 1;
449 if(!one_level_allocator_propagation_test<MultiSet>())
450 return 1;
451 //sequence containers
452 if(!one_level_allocator_propagation_test<Vector>())
453 return 1;
454 if(!one_level_allocator_propagation_test<Deque>())
455 return 1;
456 if(!one_level_allocator_propagation_test<List>())
457 return 1;
458 if(!one_level_allocator_propagation_test<Slist>())
459 return 1;
460 if(!one_level_allocator_propagation_test<StableVector>())
461 return 1;
462 if(!one_level_allocator_propagation_test<SmallVector>())
463 return 1;
464 return 0;
465}
466

source code of boost/libs/container/test/scoped_allocator_usage_test.cpp