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
27 template <typename Ty>
28 class SimpleAllocator
29 {
30 public:
31 typedef Ty value_type;
32
SimpleAllocator(int value)33 explicit SimpleAllocator(int value)
34 : m_state(value)
35 {}
36
37 template <typename T>
SimpleAllocator(const SimpleAllocator<T> & other)38 SimpleAllocator(const SimpleAllocator<T> &other)
39 : m_state(other.m_state)
40 {}
41
allocate(std::size_t n)42 Ty* allocate(std::size_t n)
43 {
44 return m_allocator.allocate(n);
45 }
46
deallocate(Ty * p,std::size_t n)47 void deallocate(Ty* p, std::size_t n)
48 {
49 m_allocator.deallocate(p, n);
50 }
51
get_value() const52 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
operator ==(const SimpleAllocator & a,const SimpleAllocator & b)61 friend bool operator == (const SimpleAllocator &a, const SimpleAllocator &b)
62 { return a.m_state == b.m_state; }
63
operator !=(const SimpleAllocator & a,const SimpleAllocator & b)64 friend bool operator != (const SimpleAllocator &a, const SimpleAllocator &b)
65 { return a.m_state != b.m_state; }
66 };
67
68 class 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
alloc_int(BOOST_RV_REF (alloc_int)other)77 alloc_int(BOOST_RV_REF(alloc_int)other)
78 : m_value(other.m_value), m_allocator(boost::move(other.m_allocator))
79 {
80 other.m_value = -1;
81 }
82
alloc_int(BOOST_RV_REF (alloc_int)other,const allocator_type & allocator)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
alloc_int(const alloc_int & other)89 alloc_int(const alloc_int &other)
90 : m_value(other.m_value), m_allocator(boost::move(other.m_allocator))
91 {
92 }
93
alloc_int(const alloc_int & other,const allocator_type & allocator)94 alloc_int(const alloc_int &other, const allocator_type &allocator)
95 : m_value(other.m_value), m_allocator(allocator)
96 {
97 }
98
alloc_int(int value,const allocator_type & allocator)99 alloc_int(int value, const allocator_type &allocator)
100 : m_value(value), m_allocator(allocator)
101 {}
102
operator =(BOOST_RV_REF (alloc_int)other)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
operator =(const alloc_int & other)110 alloc_int & operator=(const alloc_int &other)
111 {
112 m_value = other.m_value;
113 return *this;
114 }
115
get_allocator_state() const116 int get_allocator_state() const
117 { return m_allocator.get_value(); }
118
get_value() const119 int get_value() const
120 { return m_value; }
121
operator <(const alloc_int & l,const alloc_int & r)122 friend bool operator < (const alloc_int &l, const alloc_int &r)
123 { return l.m_value < r.m_value; }
124
operator ==(const alloc_int & l,const alloc_int & r)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
133 using namespace ::boost::container;
134
135 //general allocator
136 typedef scoped_allocator_adaptor<SimpleAllocator<alloc_int> > AllocIntAllocator;
137
138 //[multi]map/set
139 typedef std::pair<const alloc_int, alloc_int> MapNode;
140 typedef scoped_allocator_adaptor<SimpleAllocator<MapNode> > MapAllocator;
141 typedef map<alloc_int, alloc_int, std::less<alloc_int>, MapAllocator> Map;
142 typedef set<alloc_int, std::less<alloc_int>, AllocIntAllocator> Set;
143 typedef multimap<alloc_int, alloc_int, std::less<alloc_int>, MapAllocator> MultiMap;
144 typedef multiset<alloc_int, std::less<alloc_int>, AllocIntAllocator> MultiSet;
145
146 //[multi]flat_map/set
147 typedef std::pair<alloc_int, alloc_int> FlatMapNode;
148 typedef scoped_allocator_adaptor<SimpleAllocator<FlatMapNode> > FlatMapAllocator;
149 typedef flat_map<alloc_int, alloc_int, std::less<alloc_int>, FlatMapAllocator> FlatMap;
150 typedef flat_set<alloc_int, std::less<alloc_int>, AllocIntAllocator> FlatSet;
151 typedef flat_multimap<alloc_int, alloc_int, std::less<alloc_int>, FlatMapAllocator> FlatMultiMap;
152 typedef flat_multiset<alloc_int, std::less<alloc_int>, AllocIntAllocator> FlatMultiSet;
153
154 //vector, deque, list, slist, stable_vector.
155 typedef vector<alloc_int, AllocIntAllocator> Vector;
156 typedef deque<alloc_int, AllocIntAllocator> Deque;
157 typedef list<alloc_int, AllocIntAllocator> List;
158 typedef slist<alloc_int, AllocIntAllocator> Slist;
159 typedef stable_vector<alloc_int, AllocIntAllocator> StableVector;
160 typedef small_vector<alloc_int, 9, AllocIntAllocator> SmallVector;
161
162 /////////
163 //is_unique_assoc
164 /////////
165
166 template<class T>
167 struct is_unique_assoc
168 {
169 static const bool value = false;
170 };
171
172 template<class Key, class T, class Compare, class Allocator>
173 struct is_unique_assoc< map<Key, T, Compare, Allocator> >
174 {
175 static const bool value = true;
176 };
177
178 template<class Key, class T, class Compare, class Allocator>
179 struct is_unique_assoc< flat_map<Key, T, Compare, Allocator> >
180 {
181 static const bool value = true;
182 };
183
184 template<class Key, class Compare, class Allocator>
185 struct is_unique_assoc< set<Key, Compare, Allocator> >
186 {
187 static const bool value = true;
188 };
189
190 template<class Key, class Compare, class Allocator>
191 struct is_unique_assoc< flat_set<Key, Compare, Allocator> >
192 {
193 static const bool value = true;
194 };
195
196
197 /////////
198 //is_map
199 /////////
200
201 template<class T>
202 struct is_map
203 {
204 static const bool value = false;
205 };
206
207 template<class Key, class T, class Compare, class Allocator>
208 struct is_map< map<Key, T, Compare, Allocator> >
209 {
210 static const bool value = true;
211 };
212
213 template<class Key, class T, class Compare, class Allocator>
214 struct is_map< flat_map<Key, T, Compare, Allocator> >
215 {
216 static const bool value = true;
217 };
218
219 template<class Key, class T, class Compare, class Allocator>
220 struct is_map< multimap<Key, T, Compare, Allocator> >
221 {
222 static const bool value = true;
223 };
224
225 template<class Key, class T, class Compare, class Allocator>
226 struct is_map< flat_multimap<Key, T, Compare, Allocator> >
227 {
228 static const bool value = true;
229 };
230
231 template<class T>
232 struct is_set
233 {
234 static const bool value = false;
235 };
236
237 template<class Key, class Compare, class Allocator>
238 struct is_set< set<Key, Compare, Allocator> >
239 {
240 static const bool value = true;
241 };
242
243 template<class Key, class Compare, class Allocator>
244 struct is_set< flat_set<Key, Compare, Allocator> >
245 {
246 static const bool value = true;
247 };
248
249 template<class Key, class Compare, class Allocator>
250 struct is_set< multiset<Key, Compare, Allocator> >
251 {
252 static const bool value = true;
253 };
254
255 template<class Key, class Compare, class Allocator>
256 struct 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
266 template< 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 >
271 struct container_wrapper_inserter
272 {
273 typedef typename Container::const_iterator const_iterator;
274 typedef typename Container::iterator iterator;
275
276 template<class Arg>
emplacecontainer_wrapper_inserter277 static iterator emplace(Container &c, const_iterator p, const Arg &arg)
278 { return c.emplace(p, arg); }
279 };
280
281 template<class Container> //map
282 struct 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>
emplacecontainer_wrapper_inserter288 static iterator emplace(Container &c, const_iterator, const Arg &arg)
289 { return c.emplace(arg, arg).first; }
290 };
291
292 template<class Container> //set
293 struct 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>
emplacecontainer_wrapper_inserter299 static iterator emplace(Container &c, const_iterator, const Arg &arg)
300 { return c.emplace(arg).first; }
301 };
302
303 template<class Container> //multimap
304 struct 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>
emplacecontainer_wrapper_inserter310 static iterator emplace(Container &c, const_iterator, const Arg &arg)
311 { return c.emplace(arg, arg); }
312 };
313
314 //multiset
315 template<class Container> //multimap
316 struct 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>
emplacecontainer_wrapper_inserter322 static iterator emplace(Container &c, const_iterator, const Arg &arg)
323 { return c.emplace(arg); }
324 };
325
326 template< class Container>
327 struct 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
container_wrappercontainer_wrapper338 container_wrapper(const allocator_type &a)
339 : Container(a)
340 {}
341
container_wrappercontainer_wrapper342 container_wrapper(BOOST_RV_REF(container_wrapper) o, const allocator_type &a)
343 : Container(BOOST_MOVE_BASE(Container, o), a)
344 {}
345
container_wrappercontainer_wrapper346 container_wrapper(const container_wrapper &o, const allocator_type &a)
347 : Container(o, a)
348 {}
349
350 template<class Arg>
emplacecontainer_wrapper351 iterator emplace(const_iterator p, const Arg &arg)
352 { return container_wrapper_inserter<Container>::emplace(*this, p, arg); }
353 };
354
355
test_value_and_state_equals(const alloc_int & r,int value,int state)356 bool 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
359 template<class F, class S>
test_value_and_state_equals(const dtl::pair<F,S> & p,int value,int state)360 bool 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
363 template<class F, class S>
test_value_and_state_equals(const std::pair<F,S> & p,int value,int state)364 bool 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
367 template<class Container>
one_level_allocator_propagation_test()368 bool 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
main()431 int 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