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