• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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