1 | /* |
2 | Copyright 2020 Glen Joseph Fernandes |
3 | (glenjofe@gmail.com) |
4 | |
5 | Distributed under the Boost Software License, Version 1.0. |
6 | (http://www.boost.org/LICENSE_1_0.txt) |
7 | */ |
8 | #ifndef BOOST_CORE_ALLOCATOR_ACCESS_HPP |
9 | #define BOOST_CORE_ALLOCATOR_ACCESS_HPP |
10 | |
11 | #include <boost/config.hpp> |
12 | #if !defined(BOOST_NO_CXX11_ALLOCATOR) |
13 | #include <boost/core/pointer_traits.hpp> |
14 | #if !defined(BOOST_MSVC) |
15 | #include <limits> |
16 | #else |
17 | #include <memory> |
18 | #endif |
19 | #include <type_traits> |
20 | #endif |
21 | #include <new> |
22 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
23 | #include <utility> |
24 | #endif |
25 | |
26 | namespace boost { |
27 | namespace detail { |
28 | |
29 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
30 | struct alloc_false { |
31 | BOOST_STATIC_CONSTEXPR bool value = false; |
32 | }; |
33 | #else |
34 | template<class> |
35 | struct alloc_void { |
36 | typedef void type; |
37 | }; |
38 | #endif |
39 | |
40 | } /* detail */ |
41 | |
42 | template<class A> |
43 | struct allocator_value_type { |
44 | typedef typename A::value_type type; |
45 | }; |
46 | |
47 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
48 | template<class A> |
49 | struct allocator_pointer { |
50 | typedef typename A::pointer type; |
51 | }; |
52 | #elif defined(BOOST_MSVC) |
53 | template<class A> |
54 | struct allocator_pointer { |
55 | typedef typename std::allocator_traits<A>::pointer type; |
56 | }; |
57 | #else |
58 | template<class A, class = void> |
59 | struct allocator_pointer { |
60 | typedef typename A::value_type* type; |
61 | }; |
62 | |
63 | template<class A> |
64 | struct allocator_pointer<A, |
65 | typename detail::alloc_void<typename A::pointer>::type> { |
66 | typedef typename A::pointer type; |
67 | }; |
68 | #endif |
69 | |
70 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
71 | template<class A> |
72 | struct allocator_const_pointer { |
73 | typedef typename A::const_pointer type; |
74 | }; |
75 | #elif defined(BOOST_MSVC) |
76 | template<class A> |
77 | struct allocator_const_pointer { |
78 | typedef typename std::allocator_traits<A>::const_pointer type; |
79 | }; |
80 | #else |
81 | template<class A, class = void> |
82 | struct allocator_const_pointer { |
83 | typedef typename pointer_traits<typename |
84 | allocator_pointer<A>::type>::template |
85 | rebind_to<const typename A::value_type>::type type; |
86 | }; |
87 | |
88 | template<class A> |
89 | struct allocator_const_pointer<A, |
90 | typename detail::alloc_void<typename A::const_pointer>::type> { |
91 | typedef typename A::const_pointer type; |
92 | }; |
93 | #endif |
94 | |
95 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
96 | template<class A> |
97 | struct allocator_void_pointer { |
98 | typedef typename A::template rebind<void>::other::pointer type; |
99 | }; |
100 | #else |
101 | template<class A, class = void> |
102 | struct allocator_void_pointer { |
103 | typedef typename pointer_traits<typename |
104 | allocator_pointer<A>::type>::template |
105 | rebind_to<void>::type type; |
106 | }; |
107 | |
108 | template<class A> |
109 | struct allocator_void_pointer<A, |
110 | typename detail::alloc_void<typename A::void_pointer>::type> { |
111 | typedef typename A::void_pointer type; |
112 | }; |
113 | #endif |
114 | |
115 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
116 | template<class A> |
117 | struct allocator_const_void_pointer { |
118 | typedef typename A::template rebind<void>::other::const_pointer type; |
119 | }; |
120 | #else |
121 | template<class A, class = void> |
122 | struct allocator_const_void_pointer { |
123 | typedef typename pointer_traits<typename |
124 | allocator_pointer<A>::type>::template |
125 | rebind_to<const void>::type type; |
126 | }; |
127 | |
128 | template<class A> |
129 | struct allocator_const_void_pointer<A, |
130 | typename detail::alloc_void<typename A::const_void_pointer>::type> { |
131 | typedef typename A::const_void_pointer type; |
132 | }; |
133 | #endif |
134 | |
135 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
136 | template<class A> |
137 | struct allocator_difference_type { |
138 | typedef typename A::difference_type type; |
139 | }; |
140 | #elif defined(BOOST_MSVC) |
141 | template<class A> |
142 | struct allocator_difference_type { |
143 | typedef typename std::allocator_traits<A>::difference_type type; |
144 | }; |
145 | #else |
146 | template<class A, class = void> |
147 | struct allocator_difference_type { |
148 | typedef typename pointer_traits<typename |
149 | allocator_pointer<A>::type>::difference_type type; |
150 | }; |
151 | |
152 | template<class A> |
153 | struct allocator_difference_type<A, |
154 | typename detail::alloc_void<typename A::difference_type>::type> { |
155 | typedef typename A::difference_type type; |
156 | }; |
157 | #endif |
158 | |
159 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
160 | template<class A> |
161 | struct allocator_size_type { |
162 | typedef typename A::size_type type; |
163 | }; |
164 | #elif defined(BOOST_MSVC) |
165 | template<class A> |
166 | struct allocator_size_type { |
167 | typedef typename std::allocator_traits<A>::size_type type; |
168 | }; |
169 | #else |
170 | template<class A, class = void> |
171 | struct allocator_size_type { |
172 | typedef typename std::make_unsigned<typename |
173 | allocator_difference_type<A>::type>::type type; |
174 | }; |
175 | |
176 | template<class A> |
177 | struct allocator_size_type<A, |
178 | typename detail::alloc_void<typename A::size_type>::type> { |
179 | typedef typename A::size_type type; |
180 | }; |
181 | #endif |
182 | |
183 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
184 | template<class A> |
185 | struct allocator_propagate_on_container_copy_assignment { |
186 | typedef detail::alloc_false type; |
187 | }; |
188 | #else |
189 | template<class A, class = void> |
190 | struct allocator_propagate_on_container_copy_assignment { |
191 | typedef std::false_type type; |
192 | }; |
193 | |
194 | template<class A> |
195 | struct allocator_propagate_on_container_copy_assignment<A, |
196 | typename detail::alloc_void<typename |
197 | A::propagate_on_container_copy_assignment>::type> { |
198 | typedef typename A::propagate_on_container_copy_assignment type; |
199 | }; |
200 | #endif |
201 | |
202 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
203 | template<class A> |
204 | struct allocator_propagate_on_container_move_assignment { |
205 | typedef detail::alloc_false type; |
206 | }; |
207 | #else |
208 | template<class A, class = void> |
209 | struct allocator_propagate_on_container_move_assignment { |
210 | typedef std::false_type type; |
211 | }; |
212 | |
213 | template<class A> |
214 | struct allocator_propagate_on_container_move_assignment<A, |
215 | typename detail::alloc_void<typename |
216 | A::propagate_on_container_move_assignment>::type> { |
217 | typedef typename A::propagate_on_container_move_assignment type; |
218 | }; |
219 | #endif |
220 | |
221 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
222 | template<class A> |
223 | struct allocator_propagate_on_container_swap { |
224 | typedef detail::alloc_false type; |
225 | }; |
226 | #else |
227 | template<class A, class = void> |
228 | struct allocator_propagate_on_container_swap { |
229 | typedef std::false_type type; |
230 | }; |
231 | |
232 | template<class A> |
233 | struct allocator_propagate_on_container_swap<A, |
234 | typename detail::alloc_void<typename |
235 | A::propagate_on_container_swap>::type> { |
236 | typedef typename A::propagate_on_container_swap type; |
237 | }; |
238 | #endif |
239 | |
240 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
241 | template<class A> |
242 | struct allocator_is_always_equal { |
243 | typedef detail::alloc_false type; |
244 | }; |
245 | #else |
246 | template<class A, class = void> |
247 | struct allocator_is_always_equal { |
248 | typedef typename std::is_empty<A>::type type; |
249 | }; |
250 | |
251 | template<class A> |
252 | struct allocator_is_always_equal<A, |
253 | typename detail::alloc_void<typename A::is_always_equal>::type> { |
254 | typedef typename A::is_always_equal type; |
255 | }; |
256 | #endif |
257 | |
258 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
259 | template<class A, class T> |
260 | struct allocator_rebind { |
261 | typedef typename A::template rebind<T>::other type; |
262 | }; |
263 | #elif defined(BOOST_MSVC) |
264 | template<class A, class T> |
265 | struct allocator_rebind { |
266 | typedef typename std::allocator_traits<A>::template rebind_alloc<T> type; |
267 | }; |
268 | #else |
269 | namespace detail { |
270 | |
271 | template<class, class> |
272 | struct alloc_to { }; |
273 | |
274 | template<template<class, class...> class A, class T, class U, class... V> |
275 | struct alloc_to<A<U, V...>, T> { |
276 | typedef A<T, V...> type; |
277 | }; |
278 | |
279 | } /* detail */ |
280 | |
281 | template<class A, class T, class = void> |
282 | struct allocator_rebind { |
283 | typedef typename detail::alloc_to<A, T>::type type; |
284 | }; |
285 | |
286 | template<class A, class T> |
287 | struct allocator_rebind<A, T, |
288 | typename detail::alloc_void<typename A::template rebind<T>::other>::type> { |
289 | typedef typename A::template rebind<T>::other type; |
290 | }; |
291 | #endif |
292 | |
293 | template<class A> |
294 | inline typename allocator_pointer<A>::type |
295 | allocator_allocate(A& a, typename allocator_size_type<A>::type n) |
296 | { |
297 | return a.allocate(n); |
298 | } |
299 | |
300 | template<class A> |
301 | inline void |
302 | allocator_deallocate(A& a, typename allocator_pointer<A>::type p, |
303 | typename allocator_size_type<A>::type n) |
304 | { |
305 | a.deallocate(p, n); |
306 | } |
307 | |
308 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
309 | template<class A> |
310 | inline typename allocator_pointer<A>::type |
311 | allocator_allocate(A& a, typename allocator_size_type<A>::type n, |
312 | typename allocator_const_void_pointer<A>::type h) |
313 | { |
314 | return a.allocate(n, h); |
315 | } |
316 | #elif defined(BOOST_MSVC) |
317 | template<class A> |
318 | inline typename allocator_pointer<A>::type |
319 | allocator_allocate(A& a, typename allocator_size_type<A>::type n, |
320 | typename allocator_const_void_pointer<A>::type h) |
321 | { |
322 | return std::allocator_traits<A>::allocate(a, n, h); |
323 | } |
324 | #else |
325 | namespace detail { |
326 | |
327 | template<class, class, class, class = void> |
328 | struct alloc_has_allocate { |
329 | BOOST_STATIC_CONSTEXPR bool value = false; |
330 | }; |
331 | |
332 | template<class A, class N, class H> |
333 | struct alloc_has_allocate<A, N, H, |
334 | typename alloc_void<decltype(std::declval<A&>().allocate(std::declval<N>(), |
335 | std::declval<H>()))>::type> { |
336 | BOOST_STATIC_CONSTEXPR bool value = true; |
337 | }; |
338 | |
339 | } /* detail */ |
340 | |
341 | template<class A> |
342 | inline typename std::enable_if<detail::alloc_has_allocate<A, |
343 | typename allocator_size_type<A>::type, |
344 | typename allocator_const_void_pointer<A>::type>::value, |
345 | typename allocator_pointer<A>::type>::type |
346 | allocator_allocate(A& a, typename allocator_size_type<A>::type n, |
347 | typename allocator_const_void_pointer<A>::type h) |
348 | { |
349 | return a.allocate(n, h); |
350 | } |
351 | |
352 | template<class A> |
353 | inline typename std::enable_if<!detail::alloc_has_allocate<A, |
354 | typename allocator_size_type<A>::type, |
355 | typename allocator_const_void_pointer<A>::type>::value, |
356 | typename allocator_pointer<A>::type>::type |
357 | allocator_allocate(A& a, typename allocator_size_type<A>::type n, |
358 | typename allocator_const_void_pointer<A>::type) |
359 | { |
360 | return a.allocate(n); |
361 | } |
362 | #endif |
363 | |
364 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
365 | template<class A, class T> |
366 | inline void |
367 | allocator_construct(A&, T* p) |
368 | { |
369 | ::new((void*)p) T(); |
370 | } |
371 | |
372 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
373 | #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) |
374 | template<class A, class T, class V, class... Args> |
375 | inline void |
376 | allocator_construct(A&, T* p, V&& v, Args&&... args) |
377 | { |
378 | ::new((void*)p) T(std::forward<V>(v), std::forward<Args>(args)...); |
379 | } |
380 | #else |
381 | template<class A, class T, class V> |
382 | inline void |
383 | allocator_construct(A&, T* p, V&& v) |
384 | { |
385 | ::new((void*)p) T(std::forward<V>(v)); |
386 | } |
387 | #endif |
388 | #else |
389 | template<class A, class T, class V> |
390 | inline void |
391 | allocator_construct(A&, T* p, const V& v) |
392 | { |
393 | ::new((void*)p) T(v); |
394 | } |
395 | |
396 | template<class A, class T, class V> |
397 | inline void |
398 | allocator_construct(A&, T* p, V& v) |
399 | { |
400 | ::new((void*)p) T(v); |
401 | } |
402 | #endif |
403 | #elif defined(BOOST_MSVC) |
404 | template<class A, class T, class... Args> |
405 | inline void |
406 | allocator_construct(A& a, T* p, Args&&... args) |
407 | { |
408 | std::allocator_traits<A>::construct(a, p, std::forward<Args>(args)...); |
409 | } |
410 | #else |
411 | namespace detail { |
412 | |
413 | template<class, class, class, class...> |
414 | struct alloc_has_construct { |
415 | BOOST_STATIC_CONSTEXPR bool value = false; |
416 | }; |
417 | |
418 | template<class A, class T, class... Args> |
419 | struct alloc_has_construct<typename alloc_void<decltype(std::declval<A |
420 | &>().construct(std::declval<T*>(), std::declval<Args&&>()...))>::type, |
421 | A, T, Args...> { |
422 | BOOST_STATIC_CONSTEXPR bool value = true; |
423 | }; |
424 | |
425 | } /* detail */ |
426 | |
427 | template<class A, class T, class... Args> |
428 | inline typename std::enable_if<detail::alloc_has_construct<void, A, T, |
429 | Args...>::value>::type |
430 | allocator_construct(A& a, T* p, Args&&... args) |
431 | { |
432 | a.construct(p, std::forward<Args>(args)...); |
433 | } |
434 | |
435 | template<class A, class T, class... Args> |
436 | inline typename std::enable_if<!detail::alloc_has_construct<void, A, T, |
437 | Args...>::value>::type |
438 | allocator_construct(A&, T* p, Args&&... args) |
439 | { |
440 | ::new((void*)p) T(std::forward<Args>(args)...); |
441 | } |
442 | #endif |
443 | |
444 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
445 | template<class A, class T> |
446 | inline void |
447 | allocator_destroy(A&, T* p) |
448 | { |
449 | p->~T(); |
450 | (void)p; |
451 | } |
452 | #elif defined(BOOST_MSVC) |
453 | template<class A, class T> |
454 | inline void |
455 | allocator_destroy(A& a, T* p) |
456 | { |
457 | std::allocator_traits<A>::destroy(a, p); |
458 | } |
459 | #else |
460 | namespace detail { |
461 | |
462 | template<class, class, class = void> |
463 | struct alloc_has_destroy { |
464 | BOOST_STATIC_CONSTEXPR bool value = false; |
465 | }; |
466 | |
467 | template<class A, class T> |
468 | struct alloc_has_destroy<A, T, |
469 | typename alloc_void<decltype(std::declval<A |
470 | &>().destroy(std::declval<T*>()))>::type> { |
471 | BOOST_STATIC_CONSTEXPR bool value = true; |
472 | }; |
473 | |
474 | } /* detail */ |
475 | |
476 | template<class A, class T> |
477 | inline typename std::enable_if<detail::alloc_has_destroy<A, T>::value>::type |
478 | allocator_destroy(A& a, T* p) |
479 | { |
480 | a.destroy(p); |
481 | } |
482 | |
483 | template<class A, class T> |
484 | inline typename std::enable_if<!detail::alloc_has_destroy<A, T>::value>::type |
485 | allocator_destroy(A&, T* p) |
486 | { |
487 | p->~T(); |
488 | (void)p; |
489 | } |
490 | #endif |
491 | |
492 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
493 | template<class A> |
494 | inline typename allocator_size_type<A>::type |
495 | allocator_max_size(const A& a) |
496 | { |
497 | return a.max_size(); |
498 | } |
499 | #elif defined(BOOST_MSVC) |
500 | template<class A> |
501 | inline typename allocator_size_type<A>::type |
502 | allocator_max_size(const A& a) |
503 | { |
504 | return std::allocator_traits<A>::max_size(a); |
505 | } |
506 | #else |
507 | namespace detail { |
508 | |
509 | template<class, class = void> |
510 | struct alloc_has_max_size { |
511 | BOOST_STATIC_CONSTEXPR bool value = false; |
512 | }; |
513 | |
514 | template<class A> |
515 | struct alloc_has_max_size<A, |
516 | typename alloc_void<decltype(std::declval<const |
517 | A&>().max_size())>::type> { |
518 | BOOST_STATIC_CONSTEXPR bool value = true; |
519 | }; |
520 | |
521 | } /* detail */ |
522 | |
523 | template<class A> |
524 | inline typename std::enable_if<detail::alloc_has_max_size<A>::value, |
525 | typename allocator_size_type<A>::type>::type |
526 | allocator_max_size(const A& a) |
527 | { |
528 | return a.max_size(); |
529 | } |
530 | |
531 | template<class A> |
532 | inline typename std::enable_if<!detail::alloc_has_max_size<A>::value, |
533 | typename allocator_size_type<A>::type>::type |
534 | allocator_max_size(const A&) |
535 | { |
536 | return (std::numeric_limits<typename |
537 | allocator_size_type<A>::type>::max)() / sizeof(typename A::value_type); |
538 | } |
539 | #endif |
540 | |
541 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
542 | template<class A> |
543 | inline A |
544 | allocator_select_on_container_copy_construction(const A& a) |
545 | { |
546 | return a; |
547 | } |
548 | #elif defined(BOOST_MSVC) |
549 | template<class A> |
550 | inline A |
551 | allocator_select_on_container_copy_construction(const A& a) |
552 | { |
553 | return std::allocator_traits<A>::select_on_container_copy_construction(a); |
554 | } |
555 | #else |
556 | namespace detail { |
557 | |
558 | template<class, class = void> |
559 | struct alloc_has_soccc { |
560 | BOOST_STATIC_CONSTEXPR bool value = false; |
561 | }; |
562 | |
563 | template<class A> |
564 | struct alloc_has_soccc<A, |
565 | typename alloc_void<decltype(std::declval<const |
566 | A&>().select_on_container_copy_construction())>::type> { |
567 | BOOST_STATIC_CONSTEXPR bool value = true; |
568 | }; |
569 | |
570 | } /* detail */ |
571 | |
572 | template<class A> |
573 | inline typename std::enable_if<detail::alloc_has_soccc<A>::value, A>::type |
574 | allocator_select_on_container_copy_construction(const A& a) |
575 | { |
576 | return a.select_on_container_copy_construction(); |
577 | } |
578 | |
579 | template<class A> |
580 | inline typename std::enable_if<!detail::alloc_has_soccc<A>::value, A>::type |
581 | allocator_select_on_container_copy_construction(const A& a) |
582 | { |
583 | return a; |
584 | } |
585 | #endif |
586 | |
587 | #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) |
588 | template<class A> |
589 | using allocator_value_type_t = typename allocator_value_type<A>::type; |
590 | |
591 | template<class A> |
592 | using allocator_pointer_t = typename allocator_pointer<A>::type; |
593 | |
594 | template<class A> |
595 | using allocator_const_pointer_t = typename allocator_const_pointer<A>::type; |
596 | |
597 | template<class A> |
598 | using allocator_void_pointer_t = typename allocator_void_pointer<A>::type; |
599 | |
600 | template<class A> |
601 | using allocator_const_void_pointer_t = |
602 | typename allocator_const_void_pointer<A>::type; |
603 | |
604 | template<class A> |
605 | using allocator_difference_type_t = |
606 | typename allocator_difference_type<A>::type; |
607 | |
608 | template<class A> |
609 | using allocator_size_type_t = typename allocator_size_type<A>::type; |
610 | |
611 | template<class A> |
612 | using allocator_propagate_on_container_copy_assignment_t = |
613 | typename allocator_propagate_on_container_copy_assignment<A>::type; |
614 | |
615 | template<class A> |
616 | using allocator_propagate_on_container_move_assignment_t = |
617 | typename allocator_propagate_on_container_move_assignment<A>::type; |
618 | |
619 | template<class A> |
620 | using allocator_propagate_on_container_swap_t = |
621 | typename allocator_propagate_on_container_swap<A>::type; |
622 | |
623 | template<class A> |
624 | using allocator_is_always_equal_t = |
625 | typename allocator_is_always_equal<A>::type; |
626 | |
627 | template<class A, class T> |
628 | using allocator_rebind_t = typename allocator_rebind<A, T>::type; |
629 | #endif |
630 | |
631 | } /* boost */ |
632 | |
633 | #endif |
634 | |