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