2 // Copyright 2006-2011 Daniel James.
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #if !defined(BOOST_UNORDERED_TEST_CXX11_ALLOCATOR_HEADER)
7 #define BOOST_UNORDERED_TEST_CXX11_ALLOCATOR_HEADER
9 #include <boost/config.hpp>
10 #include <boost/limits.hpp>
13 #include "../helpers/fwd.hpp"
14 #include "../helpers/memory.hpp"
18 struct allocator_false
21 is_select_on_copy = 0,
22 is_propagate_on_swap = 0,
23 is_propagate_on_assign = 0,
24 is_propagate_on_move = 0,
29 struct allocator_flags_all
32 is_select_on_copy = 1,
33 is_propagate_on_swap = 1,
34 is_propagate_on_assign = 1,
35 is_propagate_on_move = 1,
40 struct select_copy : allocator_false
41 { enum { is_select_on_copy = 1 }; };
42 struct propagate_swap : allocator_false
43 { enum { is_propagate_on_swap = 1 }; };
44 struct propagate_assign : allocator_false
45 { enum { is_propagate_on_assign = 1 }; };
46 struct propagate_move : allocator_false
47 { enum { is_propagate_on_move = 1 }; };
49 struct no_select_copy : allocator_flags_all
50 { enum { is_select_on_copy = 0 }; };
51 struct no_propagate_swap : allocator_flags_all
52 { enum { is_propagate_on_swap = 0 }; };
53 struct no_propagate_assign : allocator_flags_all
54 { enum { is_propagate_on_assign = 0 }; };
55 struct no_propagate_move : allocator_flags_all
56 { enum { is_propagate_on_move = 0 }; };
58 template <typename Flag>
59 struct swap_allocator_base
61 struct propagate_on_container_swap {
62 enum { value = Flag::is_propagate_on_swap }; };
65 template <typename Flag>
66 struct assign_allocator_base
68 struct propagate_on_container_copy_assignment {
69 enum { value = Flag::is_propagate_on_assign }; };
72 template <typename Flag>
73 struct move_allocator_base
75 struct propagate_on_container_move_assignment {
76 enum { value = Flag::is_propagate_on_move }; };
81 // boostinspect:nounnamed
82 bool force_equal_allocator_value = false;
85 struct force_equal_allocator
89 explicit force_equal_allocator(bool value)
90 : old_value_(force_equal_allocator_value)
91 { force_equal_allocator_value = value; }
93 ~force_equal_allocator()
94 { force_equal_allocator_value = old_value_; }
98 struct cxx11_allocator_base
103 typedef std::size_t size_type;
104 typedef std::ptrdiff_t difference_type;
106 typedef T const* const_pointer;
107 typedef T& reference;
108 typedef T const& const_reference;
109 typedef T value_type;
111 explicit cxx11_allocator_base(int t)
112 : tag_(t), selected_(0)
114 detail::tracker.allocator_ref();
117 template <typename Y> cxx11_allocator_base(
118 cxx11_allocator_base<Y> const& x)
119 : tag_(x.tag_), selected_(x.selected_)
121 detail::tracker.allocator_ref();
124 cxx11_allocator_base(cxx11_allocator_base const& x)
125 : tag_(x.tag_), selected_(x.selected_)
127 detail::tracker.allocator_ref();
130 ~cxx11_allocator_base()
132 detail::tracker.allocator_unref();
135 pointer address(reference r)
140 const_pointer address(const_reference r)
142 return const_pointer(&r);
145 pointer allocate(size_type n) {
146 pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
147 detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
151 pointer allocate(size_type n, void const* u)
153 pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
154 detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
158 void deallocate(pointer p, size_type n)
160 // Only checking tags when propagating swap.
161 // Note that tags will be tested
162 // properly in the normal allocator.
163 detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_,
164 !force_equal_allocator_value);
165 ::operator delete((void*) p);
168 void construct(T* p, T const& t) {
169 detail::tracker.track_construct((void*) p, sizeof(T), tag_);
173 #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
174 template<typename... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
175 detail::tracker.track_construct((void*) p, sizeof(T), tag_);
176 new(p) T(boost::forward<Args>(args)...);
181 detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
185 size_type max_size() const {
186 return (std::numeric_limits<size_type>::max)();
190 template <typename T, typename Flags = propagate_swap,
191 typename Enable = void>
192 struct cxx11_allocator;
194 template <typename T, typename Flags>
195 struct cxx11_allocator<
197 typename boost::disable_if_c<Flags::is_select_on_copy>::type
198 > : public cxx11_allocator_base<T>,
199 public swap_allocator_base<Flags>,
200 public assign_allocator_base<Flags>,
201 public move_allocator_base<Flags>,
204 template <typename U> struct rebind {
205 typedef cxx11_allocator<U, Flags> other;
208 explicit cxx11_allocator(int t = 0)
209 : cxx11_allocator_base<T>(t)
213 template <typename Y> cxx11_allocator(
214 cxx11_allocator<Y, Flags> const& x)
215 : cxx11_allocator_base<T>(x)
219 cxx11_allocator(cxx11_allocator const& x)
220 : cxx11_allocator_base<T>(x)
224 // When not propagating swap, allocators are always equal
225 // to avoid undefined behaviour.
226 bool operator==(cxx11_allocator const& x) const
228 return force_equal_allocator_value || (this->tag_ == x.tag_);
231 bool operator!=(cxx11_allocator const& x) const
233 return !(*this == x);
237 template <typename T, typename Flags>
238 struct cxx11_allocator<
240 typename boost::enable_if_c<Flags::is_select_on_copy>::type
241 > : public cxx11_allocator_base<T>,
242 public swap_allocator_base<Flags>,
243 public assign_allocator_base<Flags>,
244 public move_allocator_base<Flags>,
247 cxx11_allocator select_on_container_copy_construction() const
249 cxx11_allocator tmp(*this);
254 template <typename U> struct rebind {
255 typedef cxx11_allocator<U, Flags> other;
258 explicit cxx11_allocator(int t = 0)
259 : cxx11_allocator_base<T>(t)
263 template <typename Y> cxx11_allocator(
264 cxx11_allocator<Y, Flags> const& x)
265 : cxx11_allocator_base<T>(x)
269 cxx11_allocator(cxx11_allocator const& x)
270 : cxx11_allocator_base<T>(x)
274 // When not propagating swap, allocators are always equal
275 // to avoid undefined behaviour.
276 bool operator==(cxx11_allocator const& x) const
278 return force_equal_allocator_value || (this->tag_ == x.tag_);
281 bool operator!=(cxx11_allocator const& x) const
283 return !(*this == x);
287 template <typename T, typename Flags>
288 bool equivalent_impl(
289 cxx11_allocator<T, Flags> const& x,
290 cxx11_allocator<T, Flags> const& y,
293 return x.tag_ == y.tag_;
296 // Function to check how many times an allocator has been selected,
297 // return 0 for other allocators.
299 struct convert_from_anything
301 template <typename T>
302 convert_from_anything(T const&) {}
305 inline int selected_count(convert_from_anything)
310 template <typename T, typename Flags>
311 int selected_count(cxx11_allocator<T, Flags> const& x)