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
allocator_allocate(A & a,typename allocator_size_type<A>::type n)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
allocator_deallocate(A & a,typename allocator_pointer<A>::type p,typename allocator_size_type<A>::type n)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
allocator_allocate(A & a,typename allocator_size_type<A>::type n,typename allocator_const_void_pointer<A>::type h)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
allocator_allocate(A & a,typename allocator_size_type<A>::type n,typename allocator_const_void_pointer<A>::type h)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
allocator_allocate(A & a,typename allocator_size_type<A>::type n,typename allocator_const_void_pointer<A>::type h)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
allocator_allocate(A & a,typename allocator_size_type<A>::type n,typename allocator_const_void_pointer<A>::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
allocator_construct(A &,T * p)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
allocator_construct(A &,T * p,V && v,Args &&...args)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
allocator_construct(A &,T * p,V && v)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
allocator_construct(A &,T * p,const V & v)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
allocator_construct(A &,T * p,V & v)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
allocator_construct(A & a,T * p,Args &&...args)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
allocator_construct(A & a,T * p,Args &&...args)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
allocator_construct(A &,T * p,Args &&...args)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
allocator_destroy(A &,T * p)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
allocator_destroy(A & a,T * p)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
allocator_destroy(A & a,T * p)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
allocator_destroy(A &,T * p)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
allocator_max_size(const A & a)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
allocator_max_size(const A & a)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
allocator_max_size(const A & a)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
allocator_max_size(const A &)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
allocator_select_on_container_copy_construction(const A & 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
allocator_select_on_container_copy_construction(const A & 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
allocator_select_on_container_copy_construction(const A & a)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
allocator_select_on_container_copy_construction(const A & a)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