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