• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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