]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | // Copyright 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) | |
5 | ||
7c673cae | 6 | #include <boost/detail/lightweight_test.hpp> |
7c673cae | 7 | #include <boost/limits.hpp> |
b32b8144 FG |
8 | #include <boost/static_assert.hpp> |
9 | #include <boost/type_traits/is_same.hpp> | |
10 | #include <boost/unordered/detail/implementation.hpp> | |
7c673cae FG |
11 | |
12 | // Boilerplate | |
13 | ||
b32b8144 FG |
14 | #define ALLOCATOR_METHODS(name) \ |
15 | template <typename U> struct rebind \ | |
16 | { \ | |
17 | typedef name<U> other; \ | |
18 | }; \ | |
19 | \ | |
20 | name() {} \ | |
21 | template <typename Y> name(name<Y> const&) {} \ | |
22 | T* address(T& r) { return &r; } \ | |
23 | T const* address(T const& r) { return &r; } \ | |
24 | T* allocate(std::size_t n) \ | |
25 | { \ | |
26 | return static_cast<T*>(::operator new(n * sizeof(T))); \ | |
27 | } \ | |
28 | T* allocate(std::size_t n, void const*) \ | |
29 | { \ | |
30 | return static_cast<T*>(::operator new(n * sizeof(T))); \ | |
31 | } \ | |
32 | void deallocate(T* p, std::size_t) { ::operator delete((void*)p); } \ | |
33 | void construct(T* p, T const& t) { new (p) T(t); } \ | |
34 | void destroy(T* p) { p->~T(); } \ | |
35 | std::size_t max_size() const \ | |
36 | { \ | |
37 | return (std::numeric_limits<std::size_t>::max)(); \ | |
38 | } \ | |
39 | bool operator==(name<T> const&) { return true; } \ | |
40 | bool operator!=(name<T> const&) { return false; } \ | |
7c673cae FG |
41 | /**/ |
42 | ||
b32b8144 FG |
43 | #define ALLOCATOR_METHODS_TYPEDEFS(name) \ |
44 | template <typename U> struct rebind \ | |
45 | { \ | |
46 | typedef name<U> other; \ | |
47 | }; \ | |
48 | \ | |
49 | name() {} \ | |
50 | template <typename Y> name(name<Y> const&) {} \ | |
51 | pointer address(T& r) { return &r; } \ | |
52 | const_pointer address(T const& r) { return &r; } \ | |
53 | pointer allocate(std::size_t n) \ | |
54 | { \ | |
55 | return pointer(::operator new(n * sizeof(T))); \ | |
56 | } \ | |
57 | pointer allocate(std::size_t n, void const*) \ | |
58 | { \ | |
59 | return pointer(::operator new(n * sizeof(T))); \ | |
60 | } \ | |
61 | void deallocate(pointer p, std::size_t) { ::operator delete((void*)p); } \ | |
62 | void construct(T* p, T const& t) { new (p) T(t); } \ | |
63 | void destroy(T* p) { p->~T(); } \ | |
64 | size_type max_size() const \ | |
65 | { \ | |
66 | return (std::numeric_limits<size_type>::max)(); \ | |
67 | } \ | |
68 | bool operator==(name<T> const&) { return true; } \ | |
69 | bool operator!=(name<T> const&) { return false; } \ | |
7c673cae FG |
70 | /**/ |
71 | ||
b32b8144 FG |
72 | struct yes_type |
73 | { | |
74 | enum | |
75 | { | |
76 | value = true | |
77 | }; | |
78 | }; | |
79 | struct no_type | |
80 | { | |
81 | enum | |
82 | { | |
83 | value = false | |
84 | }; | |
85 | }; | |
7c673cae FG |
86 | |
87 | // For tracking calls... | |
88 | ||
89 | static int selected; | |
b32b8144 | 90 | void reset() { selected = 0; } |
7c673cae | 91 | |
b32b8144 | 92 | template <typename Allocator> int call_select() |
7c673cae | 93 | { |
b32b8144 FG |
94 | typedef boost::unordered::detail::allocator_traits<Allocator> traits; |
95 | Allocator a; | |
7c673cae | 96 | |
b32b8144 FG |
97 | reset(); |
98 | BOOST_TEST(traits::select_on_container_copy_construction(a) == a); | |
99 | return selected; | |
7c673cae FG |
100 | } |
101 | ||
102 | // Empty allocator test | |
103 | ||
b32b8144 | 104 | template <typename T> struct empty_allocator |
7c673cae | 105 | { |
b32b8144 FG |
106 | typedef T value_type; |
107 | ALLOCATOR_METHODS(empty_allocator) | |
7c673cae FG |
108 | }; |
109 | ||
110 | void test_empty_allocator() | |
111 | { | |
b32b8144 FG |
112 | typedef empty_allocator<int> allocator; |
113 | typedef boost::unordered::detail::allocator_traits<allocator> traits; | |
7c673cae | 114 | #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1 |
b32b8144 FG |
115 | BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, |
116 | std::make_unsigned<std::ptrdiff_t>::type>::value)); | |
7c673cae | 117 | #else |
b32b8144 | 118 | BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value)); |
7c673cae | 119 | #endif |
b32b8144 FG |
120 | BOOST_STATIC_ASSERT( |
121 | (boost::is_same<traits::difference_type, std::ptrdiff_t>::value)); | |
122 | BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value)); | |
123 | BOOST_STATIC_ASSERT( | |
124 | (boost::is_same<traits::const_pointer, int const*>::value)); | |
125 | BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value)); | |
126 | BOOST_TEST(!traits::propagate_on_container_copy_assignment::value); | |
127 | BOOST_TEST(!traits::propagate_on_container_move_assignment::value); | |
128 | BOOST_TEST(!traits::propagate_on_container_swap::value); | |
129 | BOOST_TEST(call_select<allocator>() == 0); | |
7c673cae FG |
130 | } |
131 | ||
132 | // allocator 1 | |
133 | ||
b32b8144 FG |
134 | template <typename T> struct allocator1 |
135 | { | |
136 | typedef T value_type; | |
137 | ALLOCATOR_METHODS(allocator1) | |
138 | ||
139 | typedef yes_type propagate_on_container_copy_assignment; | |
140 | typedef yes_type propagate_on_container_move_assignment; | |
141 | typedef yes_type propagate_on_container_swap; | |
142 | ||
143 | allocator1<T> select_on_container_copy_construction() const | |
144 | { | |
145 | ++selected; | |
146 | return allocator1<T>(); | |
147 | } | |
7c673cae FG |
148 | }; |
149 | ||
150 | void test_allocator1() | |
151 | { | |
b32b8144 FG |
152 | typedef allocator1<int> allocator; |
153 | typedef boost::unordered::detail::allocator_traits<allocator> traits; | |
7c673cae | 154 | #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1 |
b32b8144 FG |
155 | BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, |
156 | std::make_unsigned<std::ptrdiff_t>::type>::value)); | |
7c673cae | 157 | #else |
b32b8144 | 158 | BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value)); |
7c673cae | 159 | #endif |
b32b8144 FG |
160 | BOOST_STATIC_ASSERT( |
161 | (boost::is_same<traits::difference_type, std::ptrdiff_t>::value)); | |
162 | BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value)); | |
163 | BOOST_STATIC_ASSERT( | |
164 | (boost::is_same<traits::const_pointer, int const*>::value)); | |
165 | BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value)); | |
166 | BOOST_TEST(traits::propagate_on_container_copy_assignment::value); | |
167 | BOOST_TEST(traits::propagate_on_container_move_assignment::value); | |
168 | BOOST_TEST(traits::propagate_on_container_swap::value); | |
169 | BOOST_TEST(call_select<allocator>() == 1); | |
7c673cae FG |
170 | } |
171 | ||
172 | // allocator 2 | |
173 | ||
b32b8144 | 174 | template <typename Alloc> struct allocator2_base |
7c673cae | 175 | { |
b32b8144 FG |
176 | Alloc select_on_container_copy_construction() const |
177 | { | |
178 | ++selected; | |
179 | return Alloc(); | |
180 | } | |
7c673cae FG |
181 | }; |
182 | ||
b32b8144 FG |
183 | template <typename T> struct allocator2 : allocator2_base<allocator2<T> > |
184 | { | |
185 | typedef T value_type; | |
186 | typedef T* pointer; | |
187 | typedef T const* const_pointer; | |
188 | typedef std::size_t size_type; | |
189 | ||
190 | ALLOCATOR_METHODS(allocator2) | |
191 | ||
192 | typedef no_type propagate_on_container_copy_assignment; | |
193 | typedef no_type propagate_on_container_move_assignment; | |
194 | typedef no_type propagate_on_container_swap; | |
7c673cae FG |
195 | }; |
196 | ||
197 | void test_allocator2() | |
198 | { | |
b32b8144 FG |
199 | typedef allocator2<int> allocator; |
200 | typedef boost::unordered::detail::allocator_traits<allocator> traits; | |
201 | BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value)); | |
202 | BOOST_STATIC_ASSERT( | |
203 | (boost::is_same<traits::difference_type, std::ptrdiff_t>::value)); | |
204 | BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value)); | |
205 | BOOST_STATIC_ASSERT( | |
206 | (boost::is_same<traits::const_pointer, int const*>::value)); | |
207 | BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value)); | |
208 | BOOST_TEST(!traits::propagate_on_container_copy_assignment::value); | |
209 | BOOST_TEST(!traits::propagate_on_container_move_assignment::value); | |
210 | BOOST_TEST(!traits::propagate_on_container_swap::value); | |
211 | BOOST_TEST(call_select<allocator>() == 1); | |
7c673cae FG |
212 | } |
213 | ||
214 | // allocator 3 | |
215 | ||
b32b8144 | 216 | template <typename T> struct ptr |
7c673cae | 217 | { |
b32b8144 FG |
218 | T* value_; |
219 | ||
220 | ptr(void* v) : value_((T*)v) {} | |
221 | T& operator*() const { return *value_; } | |
7c673cae FG |
222 | }; |
223 | ||
b32b8144 | 224 | template <> struct ptr<void> |
7c673cae | 225 | { |
b32b8144 FG |
226 | void* value_; |
227 | ptr(void* v) : value_(v) {} | |
7c673cae FG |
228 | }; |
229 | ||
b32b8144 | 230 | template <> struct ptr<const void> |
7c673cae | 231 | { |
b32b8144 FG |
232 | void const* value_; |
233 | ptr(void const* v) : value_(v) {} | |
7c673cae FG |
234 | }; |
235 | ||
b32b8144 | 236 | template <typename T> struct allocator3 |
7c673cae | 237 | { |
b32b8144 FG |
238 | typedef T value_type; |
239 | typedef ptr<T> pointer; | |
240 | typedef ptr<T const> const_pointer; | |
241 | typedef unsigned short size_type; | |
242 | ||
243 | ALLOCATOR_METHODS_TYPEDEFS(allocator3) | |
7c673cae | 244 | |
b32b8144 FG |
245 | typedef yes_type propagate_on_container_copy_assignment; |
246 | typedef no_type propagate_on_container_move_assignment; | |
7c673cae | 247 | |
b32b8144 FG |
248 | allocator3<T> select_on_container_copy_construction() const |
249 | { | |
250 | ++selected; | |
251 | return allocator3<T>(); | |
252 | } | |
7c673cae FG |
253 | }; |
254 | ||
255 | void test_allocator3() | |
256 | { | |
b32b8144 FG |
257 | typedef allocator3<int> allocator; |
258 | typedef boost::unordered::detail::allocator_traits<allocator> traits; | |
259 | BOOST_STATIC_ASSERT( | |
260 | (boost::is_same<traits::size_type, unsigned short>::value)); | |
261 | BOOST_STATIC_ASSERT( | |
262 | (boost::is_same<traits::difference_type, std::ptrdiff_t>::value)); | |
263 | BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value)); | |
264 | BOOST_STATIC_ASSERT( | |
265 | (boost::is_same<traits::const_pointer, ptr<int const> >::value)); | |
266 | BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value)); | |
267 | BOOST_TEST(traits::propagate_on_container_copy_assignment::value); | |
268 | BOOST_TEST(!traits::propagate_on_container_move_assignment::value); | |
269 | BOOST_TEST(!traits::propagate_on_container_swap::value); | |
270 | BOOST_TEST(call_select<allocator>() == 1); | |
7c673cae FG |
271 | } |
272 | ||
273 | int main() | |
274 | { | |
b32b8144 FG |
275 | test_empty_allocator(); |
276 | test_allocator1(); | |
277 | test_allocator2(); | |
278 | test_allocator3(); | |
279 | return boost::report_errors(); | |
7c673cae | 280 | } |