]>
Commit | Line | Data |
---|---|---|
8d59b230 | 1 | // -*- C++ -*- |
162c7cd9 SW |
2 | // Testing allocator for the C++ library testsuite. |
3 | // | |
818ab71a | 4 | // Copyright (C) 2002-2016 Free Software Foundation, Inc. |
162c7cd9 SW |
5 | // |
6 | // This file is part of the GNU ISO C++ Library. This library is free | |
7 | // software; you can redistribute it and/or modify it under the | |
8 | // terms of the GNU General Public License as published by the | |
748086b7 | 9 | // Free Software Foundation; either version 3, or (at your option) |
162c7cd9 SW |
10 | // any later version. |
11 | // | |
12 | // This library is distributed in the hope that it will be useful, | |
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | // GNU General Public License for more details. | |
16 | // | |
17 | // You should have received a copy of the GNU General Public License along | |
748086b7 JJ |
18 | // with this library; see the file COPYING3. If not see |
19 | // <http://www.gnu.org/licenses/>. | |
162c7cd9 | 20 | // |
162c7cd9 SW |
21 | |
22 | // This file provides an test instrumentation allocator that can be | |
23 | // used to verify allocation functionality of standard library | |
24 | // containers. 2002.11.25 smw | |
25 | ||
3d7c150e BK |
26 | #ifndef _GLIBCXX_TESTSUITE_ALLOCATOR_H |
27 | #define _GLIBCXX_TESTSUITE_ALLOCATOR_H | |
162c7cd9 | 28 | |
31905f34 | 29 | #include <tr1/unordered_map> |
ca0f8fd1 | 30 | #include <bits/move.h> |
f038f582 | 31 | #include <ext/pointer.h> |
5c7c5f9a | 32 | #include <ext/alloc_traits.h> |
7d9cb054 | 33 | #include <testsuite_hooks.h> |
162c7cd9 | 34 | |
aecf642c | 35 | namespace __gnu_test |
162c7cd9 | 36 | { |
9f9900db | 37 | class tracker_allocator_counter |
162c7cd9 | 38 | { |
8d59b230 BK |
39 | public: |
40 | typedef std::size_t size_type; | |
e1f3ce0d | 41 | |
5c7c5f9a | 42 | static void |
8d59b230 | 43 | allocate(size_type blocksize) |
5c7c5f9a | 44 | { allocationCount_ += blocksize; } |
e1f3ce0d | 45 | |
8d59b230 | 46 | static void |
5c7c5f9a | 47 | construct() { ++constructCount_; } |
162c7cd9 | 48 | |
8d59b230 | 49 | static void |
5c7c5f9a | 50 | destroy() { ++destructCount_; } |
162c7cd9 | 51 | |
8d59b230 | 52 | static void |
5c7c5f9a FD |
53 | deallocate(size_type blocksize) |
54 | { deallocationCount_ += blocksize; } | |
e1f3ce0d | 55 | |
8d59b230 | 56 | static size_type |
9f9900db | 57 | get_allocation_count() { return allocationCount_; } |
e1f3ce0d | 58 | |
8d59b230 | 59 | static size_type |
9f9900db | 60 | get_deallocation_count() { return deallocationCount_; } |
e1f3ce0d | 61 | |
8d59b230 | 62 | static int |
9f9900db | 63 | get_construct_count() { return constructCount_; } |
162c7cd9 | 64 | |
8d59b230 | 65 | static int |
9f9900db | 66 | get_destruct_count() { return destructCount_; } |
e1f3ce0d | 67 | |
8d59b230 | 68 | static void |
9f9900db | 69 | reset() |
8d59b230 | 70 | { |
9f9900db BK |
71 | allocationCount_ = 0; |
72 | deallocationCount_ = 0; | |
8d59b230 | 73 | constructCount_ = 0; |
9f9900db | 74 | destructCount_ = 0; |
8d59b230 | 75 | } |
162c7cd9 SW |
76 | |
77 | private: | |
9f9900db BK |
78 | static size_type allocationCount_; |
79 | static size_type deallocationCount_; | |
8d59b230 BK |
80 | static int constructCount_; |
81 | static int destructCount_; | |
82 | }; | |
83 | ||
5c7c5f9a FD |
84 | // Helper to detect inconsistency between type used to instantiate an |
85 | // allocator and the underlying allocator value_type. | |
86 | template<typename T, typename Alloc, | |
87 | typename = typename Alloc::value_type> | |
88 | struct check_consistent_alloc_value_type; | |
89 | ||
90 | template<typename T, typename Alloc> | |
91 | struct check_consistent_alloc_value_type<T, Alloc, T> | |
92 | { typedef T value_type; }; | |
93 | ||
94 | // An allocator facade that intercepts allocate/deallocate/construct/destroy | |
95 | // calls and track them through the tracker_allocator_counter class. This | |
96 | // class is templated on the target object type, but tracker isn't. | |
97 | template<typename T, typename Alloc = std::allocator<T> > | |
98 | class tracker_allocator : public Alloc | |
99 | { | |
100 | private: | |
101 | typedef tracker_allocator_counter counter_type; | |
162c7cd9 | 102 | |
5c7c5f9a | 103 | typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits; |
8274b281 | 104 | |
5c7c5f9a FD |
105 | public: |
106 | typedef typename | |
107 | check_consistent_alloc_value_type<T, Alloc>::value_type value_type; | |
108 | typedef typename AllocTraits::pointer pointer; | |
109 | typedef typename AllocTraits::size_type size_type; | |
8274b281 | 110 | |
5c7c5f9a FD |
111 | template<class U> |
112 | struct rebind | |
113 | { | |
114 | typedef tracker_allocator<U, | |
115 | typename AllocTraits::template rebind<U>::other> other; | |
116 | }; | |
117 | ||
118 | #if __cplusplus >= 201103L | |
119 | tracker_allocator() = default; | |
120 | tracker_allocator(const tracker_allocator&) = default; | |
121 | tracker_allocator(tracker_allocator&&) = default; | |
5caff414 JW |
122 | tracker_allocator& operator=(const tracker_allocator&) = default; |
123 | tracker_allocator& operator=(tracker_allocator&&) = default; | |
5c7c5f9a FD |
124 | |
125 | // Perfect forwarding constructor. | |
126 | template<typename... _Args> | |
127 | tracker_allocator(_Args&&... __args) | |
128 | : Alloc(std::forward<_Args>(__args)...) | |
129 | { } | |
130 | #else | |
131 | tracker_allocator() | |
132 | { } | |
162c7cd9 | 133 | |
5c7c5f9a | 134 | tracker_allocator(const tracker_allocator&) |
b3fb198d | 135 | { } |
162c7cd9 | 136 | |
5c7c5f9a FD |
137 | ~tracker_allocator() |
138 | { } | |
139 | #endif | |
162c7cd9 | 140 | |
5c7c5f9a FD |
141 | template<class U> |
142 | tracker_allocator(const tracker_allocator<U, | |
143 | typename AllocTraits::template rebind<U>::other>& alloc) | |
144 | _GLIBCXX_USE_NOEXCEPT | |
145 | : Alloc(alloc) | |
146 | { } | |
162c7cd9 | 147 | |
5c7c5f9a FD |
148 | pointer |
149 | allocate(size_type n, const void* = 0) | |
150 | { | |
151 | pointer p = AllocTraits::allocate(*this, n); | |
152 | counter_type::allocate(n * sizeof(T)); | |
153 | return p; | |
154 | } | |
b3fb198d | 155 | |
8274b281 | 156 | #if __cplusplus >= 201103L |
5c7c5f9a FD |
157 | template<typename U, typename... Args> |
158 | void | |
159 | construct(U* p, Args&&... args) | |
160 | { | |
161 | AllocTraits::construct(*this, p, std::forward<Args>(args)...); | |
162 | counter_type::construct(); | |
163 | } | |
164 | ||
165 | template<typename U> | |
166 | void | |
167 | destroy(U* p) | |
168 | { | |
169 | AllocTraits::destroy(*this, p); | |
170 | counter_type::destroy(); | |
171 | } | |
172 | #else | |
6c6424b3 | 173 | void |
5c7c5f9a | 174 | construct(pointer p, const T& value) |
6c6424b3 | 175 | { |
5c7c5f9a | 176 | AllocTraits::construct(*this, p, value); |
6c6424b3 JW |
177 | counter_type::construct(); |
178 | } | |
179 | ||
6c6424b3 | 180 | void |
5c7c5f9a | 181 | destroy(pointer p) |
6c6424b3 | 182 | { |
5c7c5f9a | 183 | AllocTraits::destroy(*this, p); |
6c6424b3 JW |
184 | counter_type::destroy(); |
185 | } | |
8274b281 | 186 | #endif |
162c7cd9 | 187 | |
5c7c5f9a FD |
188 | void |
189 | deallocate(pointer p, size_type num) | |
190 | { | |
191 | counter_type::deallocate(num * sizeof(T)); | |
192 | AllocTraits::deallocate(*this, p, num); | |
193 | } | |
b3fb198d | 194 | |
5c7c5f9a FD |
195 | // Implement swap for underlying allocators that might need it. |
196 | friend inline void | |
197 | swap(tracker_allocator& a, tracker_allocator& b) | |
198 | { | |
199 | using std::swap; | |
200 | ||
201 | Alloc& aa = a; | |
202 | Alloc& ab = b; | |
203 | swap(aa, ab); | |
204 | } | |
205 | }; | |
206 | ||
207 | template<class T1, class Alloc1, class T2, class Alloc2> | |
8d59b230 | 208 | bool |
5c7c5f9a FD |
209 | operator==(const tracker_allocator<T1, Alloc1>& lhs, |
210 | const tracker_allocator<T2, Alloc2>& rhs) throw() | |
211 | { | |
212 | const Alloc1& alloc1 = lhs; | |
213 | const Alloc2& alloc2 = rhs; | |
2acb7096 | 214 | return alloc1 == alloc2; |
5c7c5f9a | 215 | } |
8d59b230 | 216 | |
5c7c5f9a | 217 | template<class T1, class Alloc1, class T2, class Alloc2> |
8d59b230 | 218 | bool |
5c7c5f9a FD |
219 | operator!=(const tracker_allocator<T1, Alloc1>& lhs, |
220 | const tracker_allocator<T2, Alloc2>& rhs) throw() | |
221 | { return !(lhs == rhs); } | |
1985f1cd | 222 | |
8bfd0a46 BK |
223 | bool |
224 | check_construct_destroy(const char* tag, int expected_c, int expected_d); | |
1985f1cd | 225 | |
5d1b2a1e | 226 | template<typename Alloc> |
001a2a47 | 227 | bool |
5d1b2a1e BK |
228 | check_deallocate_null() |
229 | { | |
230 | // Let's not core here... | |
5c7c5f9a | 231 | Alloc a; |
8fc81078 PC |
232 | a.deallocate(0, 1); |
233 | a.deallocate(0, 10); | |
001a2a47 | 234 | return true; |
5d1b2a1e | 235 | } |
a063e891 PC |
236 | |
237 | template<typename Alloc> | |
238 | bool | |
239 | check_allocate_max_size() | |
240 | { | |
241 | Alloc a; | |
242 | try | |
243 | { | |
244 | a.allocate(a.max_size() + 1); | |
245 | } | |
246 | catch(std::bad_alloc&) | |
247 | { | |
248 | return true; | |
249 | } | |
250 | catch(...) | |
251 | { | |
252 | throw; | |
253 | } | |
254 | throw; | |
255 | } | |
0cb855b7 | 256 | |
31905f34 PC |
257 | // A simple allocator which can be constructed endowed of a given |
258 | // "personality" (an integer), queried in operator== to simulate the | |
259 | // behavior of realworld "unequal" allocators (i.e., not exploiting | |
260 | // the provision in 20.1.5/4, first bullet). A global unordered_map, | |
261 | // filled at allocation time with (pointer, personality) pairs, is | |
262 | // then consulted to enforce the requirements in Table 32 about | |
263 | // deallocation vs allocator equality. Note that this allocator is | |
5c7c5f9a | 264 | // swappable, not copy assignable, consistently with Option 3 of DR 431 |
31905f34 PC |
265 | // (see N1599). |
266 | struct uneq_allocator_base | |
267 | { | |
268 | typedef std::tr1::unordered_map<void*, int> map_type; | |
269 | ||
270 | // Avoid static initialization troubles and/or bad interactions | |
271 | // with tests linking testsuite_allocator.o and playing globally | |
272 | // with operator new/delete. | |
273 | static map_type& | |
274 | get_map() | |
275 | { | |
276 | static map_type alloc_map; | |
277 | return alloc_map; | |
278 | } | |
279 | }; | |
280 | ||
5c7c5f9a | 281 | template<typename Tp, typename Alloc = std::allocator<Tp> > |
31905f34 | 282 | class uneq_allocator |
5c7c5f9a FD |
283 | : private uneq_allocator_base, |
284 | public Alloc | |
31905f34 | 285 | { |
5c7c5f9a FD |
286 | typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits; |
287 | ||
288 | Alloc& base() { return *this; } | |
289 | const Alloc& base() const { return *this; } | |
290 | void swap_base(Alloc& b) { swap(b, this->base()); } | |
291 | ||
31905f34 | 292 | public: |
5c7c5f9a FD |
293 | typedef typename check_consistent_alloc_value_type<Tp, Alloc>::value_type |
294 | value_type; | |
295 | typedef typename AllocTraits::size_type size_type; | |
296 | typedef typename AllocTraits::pointer pointer; | |
920a97b7 | 297 | |
734f5023 | 298 | #if __cplusplus >= 201103L |
5c7c5f9a | 299 | typedef std::true_type propagate_on_container_swap; |
920a97b7 JW |
300 | #endif |
301 | ||
31905f34 | 302 | template<typename Tp1> |
5c7c5f9a FD |
303 | struct rebind |
304 | { | |
305 | typedef uneq_allocator<Tp1, | |
306 | typename AllocTraits::template rebind<Tp1>::other> other; | |
307 | }; | |
31905f34 | 308 | |
7d9cb054 | 309 | uneq_allocator() _GLIBCXX_USE_NOEXCEPT |
31905f34 PC |
310 | : personality(0) { } |
311 | ||
7d9cb054 | 312 | uneq_allocator(int person) _GLIBCXX_USE_NOEXCEPT |
31905f34 | 313 | : personality(person) { } |
5c7c5f9a FD |
314 | |
315 | #if __cplusplus >= 201103L | |
316 | uneq_allocator(const uneq_allocator&) = default; | |
317 | uneq_allocator(uneq_allocator&&) = default; | |
318 | #endif | |
31905f34 PC |
319 | |
320 | template<typename Tp1> | |
5c7c5f9a FD |
321 | uneq_allocator(const uneq_allocator<Tp1, |
322 | typename AllocTraits::template rebind<Tp1>::other>& b) | |
323 | _GLIBCXX_USE_NOEXCEPT | |
31905f34 PC |
324 | : personality(b.get_personality()) { } |
325 | ||
7d9cb054 PC |
326 | ~uneq_allocator() _GLIBCXX_USE_NOEXCEPT |
327 | { } | |
328 | ||
31905f34 PC |
329 | int get_personality() const { return personality; } |
330 | ||
331 | pointer | |
5c7c5f9a | 332 | allocate(size_type n, const void* hint = 0) |
31905f34 | 333 | { |
5c7c5f9a FD |
334 | pointer p = AllocTraits::allocate(*this, n); |
335 | ||
31905f34 PC |
336 | try |
337 | { | |
338 | get_map().insert(map_type::value_type(reinterpret_cast<void*>(p), | |
339 | personality)); | |
340 | } | |
341 | catch(...) | |
342 | { | |
5c7c5f9a | 343 | AllocTraits::deallocate(*this, p, n); |
31905f34 PC |
344 | __throw_exception_again; |
345 | } | |
5c7c5f9a | 346 | |
31905f34 PC |
347 | return p; |
348 | } | |
7d9cb054 | 349 | |
31905f34 | 350 | void |
5c7c5f9a | 351 | deallocate(pointer p, size_type n) |
31905f34 | 352 | { |
7d9cb054 PC |
353 | bool test __attribute__((unused)) = true; |
354 | ||
355 | VERIFY( p ); | |
356 | ||
31905f34 | 357 | map_type::iterator it = get_map().find(reinterpret_cast<void*>(p)); |
7d9cb054 | 358 | VERIFY( it != get_map().end() ); |
31905f34 PC |
359 | |
360 | // Enforce requirements in Table 32 about deallocation vs | |
361 | // allocator equality. | |
7d9cb054 PC |
362 | VERIFY( it->second == personality ); |
363 | ||
31905f34 | 364 | get_map().erase(it); |
5c7c5f9a | 365 | AllocTraits::deallocate(*this, p, n); |
31905f34 | 366 | } |
7d9cb054 | 367 | |
734f5023 | 368 | #if __cplusplus >= 201103L |
173f26ae PC |
369 | // Not copy assignable... |
370 | uneq_allocator& | |
371 | operator=(const uneq_allocator&) = delete; | |
8274b281 | 372 | |
5c7c5f9a FD |
373 | // ... but still moveable if base allocator is. |
374 | uneq_allocator& | |
375 | operator=(uneq_allocator&&) = default; | |
376 | #else | |
6c6424b3 | 377 | private: |
31905f34 PC |
378 | // Not assignable... |
379 | uneq_allocator& | |
380 | operator=(const uneq_allocator&); | |
173f26ae | 381 | #endif |
31905f34 | 382 | |
6c6424b3 | 383 | private: |
31905f34 PC |
384 | // ... yet swappable! |
385 | friend inline void | |
386 | swap(uneq_allocator& a, uneq_allocator& b) | |
5c7c5f9a FD |
387 | { |
388 | std::swap(a.personality, b.personality); | |
389 | a.swap_base(b); | |
390 | } | |
391 | ||
31905f34 | 392 | template<typename Tp1> |
5c7c5f9a FD |
393 | friend inline bool |
394 | operator==(const uneq_allocator& a, | |
395 | const uneq_allocator<Tp1, | |
396 | typename AllocTraits::template rebind<Tp1>::other>& b) | |
397 | { return a.personality == b.personality; } | |
31905f34 PC |
398 | |
399 | template<typename Tp1> | |
5c7c5f9a FD |
400 | friend inline bool |
401 | operator!=(const uneq_allocator& a, | |
402 | const uneq_allocator<Tp1, | |
403 | typename AllocTraits::template rebind<Tp1>::other>& b) | |
404 | { return !(a == b); } | |
31905f34 PC |
405 | |
406 | int personality; | |
407 | }; | |
bd8485dc | 408 | |
734f5023 | 409 | #if __cplusplus >= 201103L |
bd8485dc | 410 | // An uneq_allocator which can be used to test allocator propagation. |
5c7c5f9a FD |
411 | template<typename Tp, bool Propagate, typename Alloc = std::allocator<Tp>> |
412 | class propagating_allocator : public uneq_allocator<Tp, Alloc> | |
bd8485dc | 413 | { |
5c7c5f9a FD |
414 | typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits; |
415 | ||
416 | typedef uneq_allocator<Tp, Alloc> base_alloc; | |
bd8485dc JW |
417 | base_alloc& base() { return *this; } |
418 | const base_alloc& base() const { return *this; } | |
419 | void swap_base(base_alloc& b) { swap(b, this->base()); } | |
420 | ||
421 | typedef std::integral_constant<bool, Propagate> trait_type; | |
422 | ||
423 | public: | |
73f05031 JW |
424 | // default allocator_traits::rebind_alloc would select |
425 | // uneq_allocator::rebind so we must define rebind here | |
bd8485dc | 426 | template<typename Up> |
5c7c5f9a FD |
427 | struct rebind |
428 | { | |
429 | typedef propagating_allocator<Up, Propagate, | |
430 | typename AllocTraits::template rebind<Up>::other> other; | |
431 | }; | |
bd8485dc JW |
432 | |
433 | propagating_allocator(int i) noexcept | |
434 | : base_alloc(i) | |
435 | { } | |
436 | ||
437 | template<typename Up> | |
5c7c5f9a FD |
438 | propagating_allocator(const propagating_allocator<Up, Propagate, |
439 | typename AllocTraits::template rebind<Up>::other>& a) | |
440 | noexcept | |
bd8485dc JW |
441 | : base_alloc(a) |
442 | { } | |
443 | ||
444 | propagating_allocator() noexcept = default; | |
445 | ||
446 | propagating_allocator(const propagating_allocator&) noexcept = default; | |
447 | ||
a2e70335 JM |
448 | propagating_allocator& |
449 | operator=(const propagating_allocator& a) noexcept | |
ff90a89e JW |
450 | { |
451 | static_assert(Propagate, "assigning propagating_allocator<T, true>"); | |
452 | propagating_allocator(a).swap_base(*this); | |
453 | return *this; | |
454 | } | |
a2e70335 | 455 | |
bd8485dc | 456 | template<bool P2> |
5c7c5f9a FD |
457 | propagating_allocator& |
458 | operator=(const propagating_allocator<Tp, P2, Alloc>& a) noexcept | |
bd8485dc JW |
459 | { |
460 | static_assert(P2, "assigning propagating_allocator<T, true>"); | |
461 | propagating_allocator(a).swap_base(*this); | |
0f509bb7 | 462 | return *this; |
bd8485dc JW |
463 | } |
464 | ||
465 | // postcondition: a.get_personality() == 0 | |
466 | propagating_allocator(propagating_allocator&& a) noexcept | |
467 | : base_alloc() | |
468 | { swap_base(a); } | |
469 | ||
470 | // postcondition: a.get_personality() == 0 | |
471 | propagating_allocator& | |
472 | operator=(propagating_allocator&& a) noexcept | |
473 | { | |
474 | propagating_allocator(std::move(a)).swap_base(*this); | |
475 | return *this; | |
476 | } | |
477 | ||
478 | typedef trait_type propagate_on_container_copy_assignment; | |
479 | typedef trait_type propagate_on_container_move_assignment; | |
480 | typedef trait_type propagate_on_container_swap; | |
481 | ||
482 | propagating_allocator select_on_container_copy_construction() const | |
483 | { return Propagate ? *this : propagating_allocator(); } | |
484 | }; | |
485 | ||
73f05031 JW |
486 | // Class template supporting the minimal interface that satisfies the |
487 | // Allocator requirements, from example in [allocator.requirements] | |
488 | template <class Tp> | |
489 | struct SimpleAllocator | |
490 | { | |
491 | typedef Tp value_type; | |
492 | ||
d9dcda6f | 493 | SimpleAllocator() noexcept { } |
73f05031 JW |
494 | |
495 | template <class T> | |
32e6a60e | 496 | SimpleAllocator(const SimpleAllocator<T>&) { } |
73f05031 JW |
497 | |
498 | Tp *allocate(std::size_t n) | |
499 | { return std::allocator<Tp>().allocate(n); } | |
500 | ||
501 | void deallocate(Tp *p, std::size_t n) | |
502 | { std::allocator<Tp>().deallocate(p, n); } | |
503 | }; | |
504 | ||
505 | template <class T, class U> | |
506 | bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&) | |
507 | { return true; } | |
508 | template <class T, class U> | |
509 | bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&) | |
510 | { return false; } | |
511 | ||
bd8485dc JW |
512 | #endif |
513 | ||
ff15f019 PC |
514 | template<typename Tp> |
515 | struct ExplicitConsAlloc : std::allocator<Tp> | |
516 | { | |
517 | ExplicitConsAlloc() { } | |
518 | ||
519 | template<typename Up> | |
520 | explicit | |
521 | ExplicitConsAlloc(const ExplicitConsAlloc<Up>&) { } | |
522 | ||
523 | template<typename Up> | |
524 | struct rebind | |
525 | { typedef ExplicitConsAlloc<Up> other; }; | |
526 | }; | |
527 | ||
f038f582 JW |
528 | #if __cplusplus >= 201103L |
529 | template<typename Tp> | |
530 | class CustomPointerAlloc : public std::allocator<Tp> | |
531 | { | |
532 | template<typename Up, typename Sp = __gnu_cxx::_Std_pointer_impl<Up>> | |
533 | using Ptr = __gnu_cxx::_Pointer_adapter<Sp>; | |
534 | ||
535 | public: | |
536 | CustomPointerAlloc() = default; | |
537 | ||
538 | template<typename Up> | |
539 | CustomPointerAlloc(const CustomPointerAlloc<Up>&) { } | |
540 | ||
541 | template<typename Up> | |
542 | struct rebind | |
543 | { typedef CustomPointerAlloc<Up> other; }; | |
544 | ||
545 | typedef Ptr<Tp> pointer; | |
546 | typedef Ptr<const Tp> const_pointer; | |
547 | typedef Ptr<void> void_pointer; | |
548 | typedef Ptr<const void> const_void_pointer; | |
549 | ||
550 | pointer allocate(std::size_t n, pointer = {}) | |
551 | { return pointer(std::allocator<Tp>::allocate(n)); } | |
552 | ||
553 | void deallocate(pointer p, std::size_t n) | |
554 | { std::allocator<Tp>::deallocate(std::addressof(*p), n); } | |
555 | }; | |
20067423 JW |
556 | |
557 | // Utility for use as CRTP base class of custom pointer types | |
558 | template<typename Derived, typename T> | |
559 | struct PointerBase | |
560 | { | |
561 | typedef T element_type; | |
562 | ||
563 | // typedefs for iterator_traits | |
564 | typedef T value_type; | |
565 | typedef std::ptrdiff_t difference_type; | |
566 | typedef std::random_access_iterator_tag iterator_category; | |
567 | typedef Derived pointer; | |
568 | typedef T& reference; | |
569 | ||
570 | T* value; | |
571 | ||
572 | explicit PointerBase(T* p = nullptr) : value(p) { } | |
573 | ||
574 | template<typename D, typename U, | |
575 | typename = decltype(static_cast<T*>(std::declval<U*>()))> | |
576 | PointerBase(const PointerBase<D, U>& p) : value(p.value) { } | |
577 | ||
578 | T& operator*() const { return *value; } | |
579 | T* operator->() const { return value; } | |
a7890973 | 580 | T& operator[](difference_type n) const { return value[n]; } |
20067423 JW |
581 | |
582 | Derived& operator++() { ++value; return derived(); } | |
583 | Derived operator++(int) { Derived tmp(derived()); ++value; return tmp; } | |
584 | Derived& operator--() { --value; return derived(); } | |
585 | Derived operator--(int) { Derived tmp(derived()); --value; return tmp; } | |
586 | ||
587 | Derived& operator+=(difference_type n) { value += n; return derived(); } | |
588 | Derived& operator-=(difference_type n) { value -= n; return derived(); } | |
589 | ||
590 | explicit operator bool() const { return value != nullptr; } | |
591 | ||
592 | Derived | |
593 | operator+(difference_type n) const | |
594 | { | |
595 | Derived p(derived()); | |
596 | return p += n; | |
597 | } | |
598 | ||
599 | Derived | |
600 | operator-(difference_type n) const | |
601 | { | |
602 | Derived p(derived()); | |
603 | return p -= n; | |
604 | } | |
605 | ||
606 | private: | |
607 | Derived& derived() { return static_cast<Derived&>(*this); } | |
608 | }; | |
609 | ||
610 | template<typename D, typename T> | |
611 | std::ptrdiff_t operator-(PointerBase<D, T> l, PointerBase<D, T> r) | |
612 | { return l.value - r.value; } | |
613 | ||
614 | template<typename D, typename T> | |
615 | bool operator==(PointerBase<D, T> l, PointerBase<D, T> r) | |
616 | { return l.value == r.value; } | |
617 | ||
618 | template<typename D, typename T> | |
619 | bool operator!=(PointerBase<D, T> l, PointerBase<D, T> r) | |
620 | { return l.value != r.value; } | |
621 | ||
622 | // implementation for void specializations | |
623 | template<typename T> | |
624 | struct PointerBase_void | |
625 | { | |
626 | typedef T element_type; | |
627 | ||
628 | // typedefs for iterator_traits | |
629 | typedef T value_type; | |
630 | typedef std::ptrdiff_t difference_type; | |
631 | typedef std::random_access_iterator_tag iterator_category; | |
632 | ||
633 | T* value; | |
634 | ||
635 | explicit PointerBase_void(T* p = nullptr) : value(p) { } | |
636 | ||
637 | template<typename D, typename U, | |
638 | typename = decltype(static_cast<T*>(std::declval<U*>()))> | |
639 | PointerBase_void(const PointerBase<D, U>& p) : value(p.value) { } | |
640 | ||
641 | explicit operator bool() const { return value != nullptr; } | |
642 | }; | |
643 | ||
644 | template<typename Derived> | |
645 | struct PointerBase<Derived, void> : PointerBase_void<void> | |
646 | { | |
647 | using PointerBase_void::PointerBase_void; | |
648 | typedef Derived pointer; | |
649 | }; | |
650 | ||
651 | template<typename Derived> | |
652 | struct PointerBase<Derived, const void> : PointerBase_void<const void> | |
653 | { | |
654 | using PointerBase_void::PointerBase_void; | |
655 | typedef Derived pointer; | |
656 | }; | |
f038f582 JW |
657 | #endif |
658 | ||
799a6e36 | 659 | } // namespace __gnu_test |
162c7cd9 | 660 | |
3d7c150e | 661 | #endif // _GLIBCXX_TESTSUITE_ALLOCATOR_H |