]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | // Copyright 2006-2009 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 | ||
6 | #if !defined(BOOST_UNORDERED_TEST_OBJECTS_HEADER) | |
7 | #define BOOST_UNORDERED_TEST_OBJECTS_HEADER | |
8 | ||
b32b8144 FG |
9 | #include "../helpers/count.hpp" |
10 | #include "../helpers/fwd.hpp" | |
11 | #include "../helpers/memory.hpp" | |
7c673cae FG |
12 | #include <boost/config.hpp> |
13 | #include <boost/limits.hpp> | |
14 | #include <cstddef> | |
7c673cae | 15 | |
b32b8144 FG |
16 | namespace test { |
17 | // Note that the default hash function will work for any equal_to (but not | |
18 | // very well). | |
19 | class object; | |
20 | class movable; | |
21 | class implicitly_convertible; | |
22 | class hash; | |
23 | class less; | |
24 | class equal_to; | |
25 | template <class T> class allocator1; | |
26 | template <class T> class allocator2; | |
27 | object generate(object const*, random_generator); | |
28 | movable generate(movable const*, random_generator); | |
29 | implicitly_convertible generate( | |
30 | implicitly_convertible const*, random_generator); | |
31 | ||
32 | inline void ignore_variable(void const*) {} | |
33 | ||
34 | class object : private counted_object | |
35 | { | |
36 | friend class hash; | |
37 | friend class equal_to; | |
38 | friend class less; | |
39 | int tag1_, tag2_; | |
40 | ||
41 | public: | |
42 | explicit object(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {} | |
43 | ||
44 | ~object() | |
45 | { | |
46 | tag1_ = -1; | |
47 | tag2_ = -1; | |
48 | } | |
7c673cae | 49 | |
b32b8144 FG |
50 | friend bool operator==(object const& x1, object const& x2) |
51 | { | |
52 | return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_; | |
53 | } | |
7c673cae | 54 | |
b32b8144 | 55 | friend bool operator!=(object const& x1, object const& x2) |
7c673cae | 56 | { |
b32b8144 FG |
57 | return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_; |
58 | } | |
7c673cae | 59 | |
b32b8144 FG |
60 | friend bool operator<(object const& x1, object const& x2) |
61 | { | |
62 | return x1.tag1_ < x2.tag1_ || | |
63 | (x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_); | |
64 | } | |
7c673cae | 65 | |
b32b8144 FG |
66 | friend object generate(object const*, random_generator g) |
67 | { | |
68 | int* x = 0; | |
69 | return object(generate(x, g), generate(x, g)); | |
70 | } | |
7c673cae | 71 | |
b32b8144 FG |
72 | friend std::ostream& operator<<(std::ostream& out, object const& o) |
73 | { | |
74 | return out << "(" << o.tag1_ << "," << o.tag2_ << ")"; | |
75 | } | |
76 | }; | |
7c673cae | 77 | |
b32b8144 FG |
78 | class movable : private counted_object |
79 | { | |
80 | friend class hash; | |
81 | friend class equal_to; | |
82 | friend class less; | |
83 | int tag1_, tag2_; | |
7c673cae | 84 | |
b32b8144 FG |
85 | BOOST_COPYABLE_AND_MOVABLE(movable) |
86 | public: | |
87 | explicit movable(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {} | |
7c673cae | 88 | |
b32b8144 FG |
89 | movable(movable const& x) |
90 | : counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_) | |
91 | { | |
92 | BOOST_TEST(x.tag1_ != -1); | |
93 | } | |
7c673cae | 94 | |
b32b8144 FG |
95 | movable(BOOST_RV_REF(movable) x) |
96 | : counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_) | |
97 | { | |
98 | BOOST_TEST(x.tag1_ != -1); | |
99 | x.tag1_ = -1; | |
100 | x.tag2_ = -1; | |
101 | } | |
102 | ||
103 | movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment | |
104 | { | |
105 | BOOST_TEST(x.tag1_ != -1); | |
106 | tag1_ = x.tag1_; | |
107 | tag2_ = x.tag2_; | |
108 | return *this; | |
109 | } | |
110 | ||
111 | movable& operator=(BOOST_RV_REF(movable) x) // Move assignment | |
112 | { | |
113 | BOOST_TEST(x.tag1_ != -1); | |
114 | tag1_ = x.tag1_; | |
115 | tag2_ = x.tag2_; | |
116 | x.tag1_ = -1; | |
117 | x.tag2_ = -1; | |
118 | return *this; | |
119 | } | |
120 | ||
121 | ~movable() | |
122 | { | |
123 | tag1_ = -1; | |
124 | tag2_ = -1; | |
125 | } | |
126 | ||
127 | friend bool operator==(movable const& x1, movable const& x2) | |
128 | { | |
129 | BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1); | |
130 | return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_; | |
131 | } | |
132 | ||
133 | friend bool operator!=(movable const& x1, movable const& x2) | |
134 | { | |
135 | BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1); | |
136 | return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_; | |
137 | } | |
138 | ||
139 | friend bool operator<(movable const& x1, movable const& x2) | |
140 | { | |
141 | BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1); | |
142 | return x1.tag1_ < x2.tag1_ || | |
143 | (x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_); | |
144 | } | |
145 | ||
146 | friend movable generate(movable const*, random_generator g) | |
147 | { | |
148 | int* x = 0; | |
149 | return movable(generate(x, g), generate(x, g)); | |
150 | } | |
151 | ||
152 | friend std::ostream& operator<<(std::ostream& out, movable const& o) | |
153 | { | |
154 | return out << "(" << o.tag1_ << "," << o.tag2_ << ")"; | |
155 | } | |
156 | }; | |
157 | ||
158 | class implicitly_convertible : private counted_object | |
159 | { | |
160 | int tag1_, tag2_; | |
161 | ||
162 | public: | |
163 | explicit implicitly_convertible(int t1 = 0, int t2 = 0) | |
164 | : tag1_(t1), tag2_(t2) | |
165 | { | |
166 | } | |
167 | ||
168 | operator object() const { return object(tag1_, tag2_); } | |
169 | ||
170 | operator movable() const { return movable(tag1_, tag2_); } | |
171 | ||
172 | friend implicitly_convertible generate( | |
173 | implicitly_convertible const*, random_generator g) | |
174 | { | |
175 | int* x = 0; | |
176 | return implicitly_convertible(generate(x, g), generate(x, g)); | |
177 | } | |
178 | ||
179 | friend std::ostream& operator<<( | |
180 | std::ostream& out, implicitly_convertible const& o) | |
181 | { | |
182 | return out << "(" << o.tag1_ << "," << o.tag2_ << ")"; | |
183 | } | |
184 | }; | |
185 | ||
186 | // Note: This is a deliberately bad hash function. | |
187 | class hash | |
188 | { | |
189 | int type_; | |
190 | ||
191 | public: | |
11fdf7f2 TL |
192 | hash() : type_(0) {} |
193 | ||
194 | explicit hash(int t) : type_(t) {} | |
b32b8144 FG |
195 | |
196 | std::size_t operator()(object const& x) const | |
197 | { | |
1e59de90 | 198 | unsigned result; |
b32b8144 FG |
199 | switch (type_) { |
200 | case 1: | |
1e59de90 | 201 | result = static_cast<unsigned>(x.tag1_); |
b32b8144 FG |
202 | break; |
203 | case 2: | |
1e59de90 | 204 | result = static_cast<unsigned>(x.tag2_); |
b32b8144 FG |
205 | break; |
206 | default: | |
1e59de90 TL |
207 | result = |
208 | static_cast<unsigned>(x.tag1_) + static_cast<unsigned>(x.tag2_); | |
b32b8144 | 209 | } |
1e59de90 | 210 | return result; |
b32b8144 FG |
211 | } |
212 | ||
213 | std::size_t operator()(movable const& x) const | |
214 | { | |
1e59de90 | 215 | unsigned result; |
b32b8144 FG |
216 | switch (type_) { |
217 | case 1: | |
1e59de90 | 218 | result = static_cast<unsigned>(x.tag1_); |
b32b8144 FG |
219 | break; |
220 | case 2: | |
1e59de90 | 221 | result = static_cast<unsigned>(x.tag2_); |
b32b8144 FG |
222 | break; |
223 | default: | |
1e59de90 TL |
224 | result = |
225 | static_cast<unsigned>(x.tag1_) + static_cast<unsigned>(x.tag2_); | |
b32b8144 | 226 | } |
1e59de90 | 227 | return result; |
b32b8144 FG |
228 | } |
229 | ||
230 | std::size_t operator()(int x) const | |
231 | { | |
232 | int result; | |
233 | switch (type_) { | |
234 | case 1: | |
235 | result = x; | |
236 | break; | |
237 | case 2: | |
238 | result = x * 7; | |
239 | break; | |
240 | default: | |
241 | result = x * 256; | |
242 | } | |
243 | return static_cast<std::size_t>(result); | |
244 | } | |
245 | ||
246 | friend bool operator==(hash const& x1, hash const& x2) | |
247 | { | |
248 | return x1.type_ == x2.type_; | |
249 | } | |
250 | ||
251 | friend bool operator!=(hash const& x1, hash const& x2) | |
252 | { | |
253 | return x1.type_ != x2.type_; | |
254 | } | |
255 | }; | |
256 | ||
257 | std::size_t hash_value(test::object const& x) { return hash()(x); } | |
258 | ||
259 | std::size_t hash_value(test::movable const& x) { return hash()(x); } | |
260 | ||
261 | class less | |
262 | { | |
263 | int type_; | |
264 | ||
265 | public: | |
266 | explicit less(int t = 0) : type_(t) {} | |
267 | ||
268 | bool operator()(object const& x1, object const& x2) const | |
269 | { | |
270 | switch (type_) { | |
271 | case 1: | |
272 | return x1.tag1_ < x2.tag1_; | |
273 | case 2: | |
274 | return x1.tag2_ < x2.tag2_; | |
275 | default: | |
276 | return x1 < x2; | |
277 | } | |
278 | } | |
279 | ||
280 | bool operator()(movable const& x1, movable const& x2) const | |
281 | { | |
282 | switch (type_) { | |
283 | case 1: | |
284 | return x1.tag1_ < x2.tag1_; | |
285 | case 2: | |
286 | return x1.tag2_ < x2.tag2_; | |
287 | default: | |
288 | return x1 < x2; | |
289 | } | |
290 | } | |
291 | ||
292 | std::size_t operator()(int x1, int x2) const { return x1 < x2; } | |
293 | ||
294 | friend bool operator==(less const& x1, less const& x2) | |
295 | { | |
296 | return x1.type_ == x2.type_; | |
297 | } | |
298 | }; | |
299 | ||
300 | class equal_to | |
301 | { | |
302 | int type_; | |
303 | ||
304 | public: | |
11fdf7f2 TL |
305 | equal_to() : type_(0) {} |
306 | ||
307 | explicit equal_to(int t) : type_(t) {} | |
b32b8144 FG |
308 | |
309 | bool operator()(object const& x1, object const& x2) const | |
310 | { | |
311 | switch (type_) { | |
312 | case 1: | |
313 | return x1.tag1_ == x2.tag1_; | |
314 | case 2: | |
315 | return x1.tag2_ == x2.tag2_; | |
316 | default: | |
317 | return x1 == x2; | |
318 | } | |
319 | } | |
320 | ||
321 | bool operator()(movable const& x1, movable const& x2) const | |
322 | { | |
323 | switch (type_) { | |
324 | case 1: | |
325 | return x1.tag1_ == x2.tag1_; | |
326 | case 2: | |
327 | return x1.tag2_ == x2.tag2_; | |
328 | default: | |
329 | return x1 == x2; | |
330 | } | |
331 | } | |
332 | ||
333 | std::size_t operator()(int x1, int x2) const { return x1 == x2; } | |
334 | ||
335 | friend bool operator==(equal_to const& x1, equal_to const& x2) | |
336 | { | |
337 | return x1.type_ == x2.type_; | |
338 | } | |
339 | ||
340 | friend bool operator!=(equal_to const& x1, equal_to const& x2) | |
341 | { | |
342 | return x1.type_ != x2.type_; | |
343 | } | |
344 | ||
345 | friend less create_compare(equal_to x) { return less(x.type_); } | |
346 | }; | |
347 | ||
348 | // allocator1 only has the old fashioned 'construct' method and has | |
349 | // a few less typedefs. allocator2 uses a custom pointer class. | |
350 | ||
351 | template <class T> class allocator1 | |
352 | { | |
353 | public: | |
354 | int tag_; | |
355 | ||
356 | typedef T value_type; | |
7c673cae | 357 | |
b32b8144 FG |
358 | template <class U> struct rebind |
359 | { | |
360 | typedef allocator1<U> other; | |
7c673cae FG |
361 | }; |
362 | ||
11fdf7f2 TL |
363 | allocator1() : tag_(0) { detail::tracker.allocator_ref(); } |
364 | ||
365 | explicit allocator1(int t) : tag_(t) { detail::tracker.allocator_ref(); } | |
b32b8144 FG |
366 | |
367 | template <class Y> allocator1(allocator1<Y> const& x) : tag_(x.tag_) | |
368 | { | |
369 | detail::tracker.allocator_ref(); | |
370 | } | |
371 | ||
372 | allocator1(allocator1 const& x) : tag_(x.tag_) | |
373 | { | |
374 | detail::tracker.allocator_ref(); | |
375 | } | |
376 | ||
377 | ~allocator1() { detail::tracker.allocator_unref(); } | |
378 | ||
379 | T* allocate(std::size_t n) | |
380 | { | |
381 | T* ptr(static_cast<T*>(::operator new(n * sizeof(T)))); | |
382 | detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); | |
383 | return ptr; | |
384 | } | |
385 | ||
386 | T* allocate(std::size_t n, void const*) | |
387 | { | |
388 | T* ptr(static_cast<T*>(::operator new(n * sizeof(T)))); | |
389 | detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); | |
390 | return ptr; | |
391 | } | |
392 | ||
393 | void deallocate(T* p, std::size_t n) | |
394 | { | |
395 | detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_); | |
396 | ::operator delete((void*)p); | |
397 | } | |
7c673cae | 398 | |
b32b8144 FG |
399 | #if BOOST_UNORDERED_CXX11_CONSTRUCTION |
400 | template <typename U, typename... Args> void construct(U* p, Args&&... args) | |
7c673cae | 401 | { |
b32b8144 FG |
402 | detail::tracker.track_construct((void*)p, sizeof(U), tag_); |
403 | new (p) U(boost::forward<Args>(args)...); | |
404 | } | |
405 | ||
406 | template <typename U> void destroy(U* p) | |
407 | { | |
408 | detail::tracker.track_destroy((void*)p, sizeof(U), tag_); | |
409 | p->~U(); | |
410 | ||
411 | // Work around MSVC buggy unused parameter warning. | |
412 | ignore_variable(&p); | |
413 | } | |
414 | #else | |
415 | private: | |
416 | // I'm going to claim in the documentation that construct/destroy | |
417 | // is never used when C++11 support isn't available, so might as | |
418 | // well check that in the text. | |
419 | // TODO: Or maybe just disallow them for values? | |
420 | template <typename U> void construct(U* p); | |
421 | template <typename U, typename A0> void construct(U* p, A0 const&); | |
422 | template <typename U, typename A0, typename A1> | |
423 | void construct(U* p, A0 const&, A1 const&); | |
424 | template <typename U, typename A0, typename A1, typename A2> | |
425 | void construct(U* p, A0 const&, A1 const&, A2 const&); | |
426 | template <typename U> void destroy(U* p); | |
427 | ||
428 | public: | |
429 | #endif | |
430 | ||
431 | bool operator==(allocator1 const& x) const { return tag_ == x.tag_; } | |
432 | ||
433 | bool operator!=(allocator1 const& x) const { return tag_ != x.tag_; } | |
434 | ||
435 | enum | |
436 | { | |
437 | is_select_on_copy = false, | |
438 | is_propagate_on_swap = false, | |
439 | is_propagate_on_assign = false, | |
440 | is_propagate_on_move = false | |
441 | }; | |
442 | }; | |
443 | ||
444 | template <class T> class ptr; | |
445 | template <class T> class const_ptr; | |
446 | ||
447 | struct void_ptr | |
448 | { | |
7c673cae | 449 | #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) |
b32b8144 FG |
450 | template <typename T> friend class ptr; |
451 | ||
452 | private: | |
7c673cae FG |
453 | #endif |
454 | ||
b32b8144 | 455 | void* ptr_; |
7c673cae | 456 | |
b32b8144 FG |
457 | public: |
458 | void_ptr() : ptr_(0) {} | |
7c673cae | 459 | |
b32b8144 | 460 | template <typename T> explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {} |
7c673cae | 461 | |
b32b8144 FG |
462 | // I'm not using the safe bool idiom because the containers should be |
463 | // able to cope with bool conversions. | |
464 | operator bool() const { return !!ptr_; } | |
7c673cae | 465 | |
b32b8144 FG |
466 | bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; } |
467 | bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; } | |
468 | }; | |
7c673cae | 469 | |
b32b8144 FG |
470 | class void_const_ptr |
471 | { | |
7c673cae | 472 | #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) |
b32b8144 FG |
473 | template <typename T> friend class const_ptr; |
474 | ||
475 | private: | |
7c673cae FG |
476 | #endif |
477 | ||
b32b8144 FG |
478 | void* ptr_; |
479 | ||
480 | public: | |
481 | void_const_ptr() : ptr_(0) {} | |
7c673cae | 482 | |
b32b8144 FG |
483 | template <typename T> |
484 | explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_) | |
485 | { | |
486 | } | |
7c673cae | 487 | |
b32b8144 FG |
488 | // I'm not using the safe bool idiom because the containers should be |
489 | // able to cope with bool conversions. | |
490 | operator bool() const { return !!ptr_; } | |
7c673cae | 491 | |
b32b8144 FG |
492 | bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; } |
493 | bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; } | |
494 | }; | |
7c673cae | 495 | |
b32b8144 FG |
496 | template <class T> class ptr |
497 | { | |
498 | friend class allocator2<T>; | |
499 | friend class const_ptr<T>; | |
500 | friend struct void_ptr; | |
7c673cae | 501 | |
b32b8144 | 502 | T* ptr_; |
7c673cae | 503 | |
b32b8144 FG |
504 | ptr(T* x) : ptr_(x) {} |
505 | ||
506 | public: | |
507 | ptr() : ptr_(0) {} | |
508 | explicit ptr(void_ptr const& x) : ptr_((T*)x.ptr_) {} | |
509 | ||
510 | T& operator*() const { return *ptr_; } | |
511 | T* operator->() const { return ptr_; } | |
512 | ptr& operator++() | |
513 | { | |
514 | ++ptr_; | |
515 | return *this; | |
516 | } | |
517 | ptr operator++(int) | |
518 | { | |
519 | ptr tmp(*this); | |
520 | ++ptr_; | |
521 | return tmp; | |
522 | } | |
523 | ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); } | |
524 | friend ptr operator+(std::ptrdiff_t s, ptr p) { return ptr<T>(s + p.ptr_); } | |
525 | T& operator[](std::ptrdiff_t s) const { return ptr_[s]; } | |
526 | bool operator!() const { return !ptr_; } | |
527 | ||
528 | // I'm not using the safe bool idiom because the containers should be | |
529 | // able to cope with bool conversions. | |
530 | operator bool() const { return !!ptr_; } | |
531 | ||
532 | bool operator==(ptr const& x) const { return ptr_ == x.ptr_; } | |
533 | bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; } | |
534 | bool operator<(ptr const& x) const { return ptr_ < x.ptr_; } | |
535 | bool operator>(ptr const& x) const { return ptr_ > x.ptr_; } | |
536 | bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; } | |
537 | bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; } | |
538 | }; | |
539 | ||
540 | template <class T> class const_ptr | |
541 | { | |
542 | friend class allocator2<T>; | |
543 | friend struct const_void_ptr; | |
544 | ||
545 | T const* ptr_; | |
546 | ||
547 | const_ptr(T const* ptr) : ptr_(ptr) {} | |
548 | ||
549 | public: | |
550 | const_ptr() : ptr_(0) {} | |
551 | const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {} | |
552 | explicit const_ptr(void_const_ptr const& x) : ptr_((T const*)x.ptr_) {} | |
553 | ||
554 | T const& operator*() const { return *ptr_; } | |
555 | T const* operator->() const { return ptr_; } | |
556 | const_ptr& operator++() | |
557 | { | |
558 | ++ptr_; | |
559 | return *this; | |
560 | } | |
561 | const_ptr operator++(int) | |
562 | { | |
563 | const_ptr tmp(*this); | |
564 | ++ptr_; | |
565 | return tmp; | |
566 | } | |
567 | const_ptr operator+(std::ptrdiff_t s) const { return const_ptr(ptr_ + s); } | |
568 | friend const_ptr operator+(std::ptrdiff_t s, const_ptr p) | |
569 | { | |
570 | return ptr<T>(s + p.ptr_); | |
571 | } | |
572 | T const& operator[](int s) const { return ptr_[s]; } | |
573 | bool operator!() const { return !ptr_; } | |
574 | operator bool() const { return !!ptr_; } | |
575 | ||
576 | bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; } | |
577 | bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; } | |
578 | bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; } | |
579 | bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; } | |
580 | bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; } | |
581 | bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; } | |
582 | }; | |
583 | ||
584 | template <class T> class allocator2 | |
585 | { | |
586 | #ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS | |
587 | public: | |
588 | #else | |
589 | template <class> friend class allocator2; | |
590 | #endif | |
591 | int tag_; | |
592 | ||
593 | public: | |
594 | typedef std::size_t size_type; | |
595 | typedef std::ptrdiff_t difference_type; | |
596 | typedef void_ptr void_pointer; | |
597 | typedef void_const_ptr const_void_pointer; | |
598 | typedef ptr<T> pointer; | |
599 | typedef const_ptr<T> const_pointer; | |
600 | typedef T& reference; | |
601 | typedef T const& const_reference; | |
602 | typedef T value_type; | |
603 | ||
604 | template <class U> struct rebind | |
605 | { | |
606 | typedef allocator2<U> other; | |
7c673cae FG |
607 | }; |
608 | ||
11fdf7f2 TL |
609 | allocator2() : tag_(0) { detail::tracker.allocator_ref(); } |
610 | ||
611 | explicit allocator2(int t) : tag_(t) { detail::tracker.allocator_ref(); } | |
b32b8144 FG |
612 | |
613 | template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_) | |
614 | { | |
615 | detail::tracker.allocator_ref(); | |
616 | } | |
617 | ||
618 | allocator2(allocator2 const& x) : tag_(x.tag_) | |
619 | { | |
620 | detail::tracker.allocator_ref(); | |
621 | } | |
622 | ||
623 | ~allocator2() { detail::tracker.allocator_unref(); } | |
624 | ||
625 | pointer address(reference r) { return pointer(&r); } | |
626 | ||
627 | const_pointer address(const_reference r) { return const_pointer(&r); } | |
628 | ||
629 | pointer allocate(size_type n) | |
630 | { | |
631 | pointer p(static_cast<T*>(::operator new(n * sizeof(T)))); | |
632 | detail::tracker.track_allocate((void*)p.ptr_, n, sizeof(T), tag_); | |
633 | return p; | |
634 | } | |
635 | ||
636 | pointer allocate(size_type n, void const*) | |
637 | { | |
638 | pointer ptr(static_cast<T*>(::operator new(n * sizeof(T)))); | |
639 | detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); | |
640 | return ptr; | |
641 | } | |
642 | ||
643 | void deallocate(pointer p, size_type n) | |
644 | { | |
645 | detail::tracker.track_deallocate((void*)p.ptr_, n, sizeof(T), tag_); | |
646 | ::operator delete((void*)p.ptr_); | |
647 | } | |
648 | ||
649 | void construct(T* p, T const& t) | |
650 | { | |
651 | detail::tracker.track_construct((void*)p, sizeof(T), tag_); | |
652 | new (p) T(t); | |
653 | } | |
7c673cae FG |
654 | |
655 | #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
b32b8144 FG |
656 | template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) |
657 | { | |
658 | detail::tracker.track_construct((void*)p, sizeof(T), tag_); | |
659 | new (p) T(boost::forward<Args>(args)...); | |
660 | } | |
7c673cae FG |
661 | #endif |
662 | ||
b32b8144 | 663 | void destroy(T* p) |
7c673cae | 664 | { |
b32b8144 FG |
665 | detail::tracker.track_destroy((void*)p, sizeof(T), tag_); |
666 | p->~T(); | |
7c673cae FG |
667 | } |
668 | ||
b32b8144 | 669 | size_type max_size() const |
7c673cae | 670 | { |
b32b8144 | 671 | return (std::numeric_limits<size_type>::max)(); |
7c673cae | 672 | } |
b32b8144 FG |
673 | |
674 | bool operator==(allocator2 const& x) const { return tag_ == x.tag_; } | |
675 | ||
676 | bool operator!=(allocator2 const& x) const { return tag_ != x.tag_; } | |
677 | ||
678 | enum | |
679 | { | |
680 | is_select_on_copy = false, | |
681 | is_propagate_on_swap = false, | |
682 | is_propagate_on_assign = false, | |
683 | is_propagate_on_move = false | |
684 | }; | |
685 | }; | |
686 | ||
687 | template <class T> | |
688 | bool equivalent_impl( | |
689 | allocator1<T> const& x, allocator1<T> const& y, test::derived_type) | |
690 | { | |
691 | return x == y; | |
692 | } | |
693 | ||
694 | template <class T> | |
695 | bool equivalent_impl( | |
696 | allocator2<T> const& x, allocator2<T> const& y, test::derived_type) | |
697 | { | |
698 | return x == y; | |
699 | } | |
7c673cae FG |
700 | } |
701 | ||
702 | #endif |