1/*
2Copyright 2020-2022 Glen Joseph Fernandes
3(glenjofe@gmail.com)
4
5Distributed 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#include <boost/core/pointer_traits.hpp>
13#include <limits>
14#include <new>
15#if !defined(BOOST_NO_CXX11_ALLOCATOR)
16#include <type_traits>
17#endif
18#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
19#include <utility>
20#endif
21
22#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 40300)
23#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T)
24#elif defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500)
25#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T)
26#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1400)
27#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T)
28#elif defined(BOOST_CLANG) && !defined(__CUDACC__)
29#if __has_feature(is_empty)
30#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T)
31#endif
32#elif defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)
33#define BOOST_DETAIL_ALLOC_EMPTY(T) __oracle_is_empty(T)
34#elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600)
35#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T)
36#elif defined(BOOST_CODEGEARC)
37#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T)
38#endif
39
40#if defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH)
41_LIBCPP_SUPPRESS_DEPRECATED_PUSH
42#endif
43#if defined(_STL_DISABLE_DEPRECATED_WARNING)
44_STL_DISABLE_DEPRECATED_WARNING
45#endif
46#if defined(_MSC_VER)
47#pragma warning(push)
48#pragma warning(disable:4996)
49#endif
50
51namespace boost {
52
53template<class A>
54struct allocator_value_type {
55 typedef typename A::value_type type;
56};
57
58namespace detail {
59
60template<class A, class = void>
61struct alloc_ptr {
62 typedef typename boost::allocator_value_type<A>::type* type;
63};
64
65template<class>
66struct alloc_void {
67 typedef void type;
68};
69
70template<class A>
71struct alloc_ptr<A,
72 typename alloc_void<typename A::pointer>::type> {
73 typedef typename A::pointer type;
74};
75
76} /* detail */
77
78template<class A>
79struct allocator_pointer {
80 typedef typename detail::alloc_ptr<A>::type type;
81};
82
83namespace detail {
84
85template<class A, class = void>
86struct alloc_const_ptr {
87 typedef typename boost::pointer_traits<typename
88 boost::allocator_pointer<A>::type>::template rebind_to<const typename
89 boost::allocator_value_type<A>::type>::type type;
90};
91
92template<class A>
93struct alloc_const_ptr<A,
94 typename alloc_void<typename A::const_pointer>::type> {
95 typedef typename A::const_pointer type;
96};
97
98} /* detail */
99
100template<class A>
101struct allocator_const_pointer {
102 typedef typename detail::alloc_const_ptr<A>::type type;
103};
104
105namespace detail {
106
107template<class, class>
108struct alloc_to { };
109
110#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
111template<template<class> class A, class T, class U>
112struct alloc_to<A<U>, T> {
113 typedef A<T> type;
114};
115
116template<template<class, class> class A, class T, class U, class V>
117struct alloc_to<A<U, V>, T> {
118 typedef A<T, V> type;
119};
120
121template<template<class, class, class> class A, class T, class U, class V1,
122 class V2>
123struct alloc_to<A<U, V1, V2>, T> {
124 typedef A<T, V1, V2> type;
125};
126#else
127template<template<class, class...> class A, class T, class U, class... V>
128struct alloc_to<A<U, V...>, T> {
129 typedef A<T, V...> type;
130};
131#endif
132
133template<class A, class T, class = void>
134struct alloc_rebind {
135 typedef typename alloc_to<A, T>::type type;
136};
137
138template<class A, class T>
139struct alloc_rebind<A, T,
140 typename alloc_void<typename A::template rebind<T>::other>::type> {
141 typedef typename A::template rebind<T>::other type;
142};
143
144} /* detail */
145
146template<class A, class T>
147struct allocator_rebind {
148 typedef typename detail::alloc_rebind<A, T>::type type;
149};
150
151namespace detail {
152
153template<class A, class = void>
154struct alloc_void_ptr {
155 typedef typename boost::pointer_traits<typename
156 boost::allocator_pointer<A>::type>::template
157 rebind_to<void>::type type;
158};
159
160template<class A>
161struct alloc_void_ptr<A,
162 typename alloc_void<typename A::void_pointer>::type> {
163 typedef typename A::void_pointer type;
164};
165
166} /* detail */
167
168template<class A>
169struct allocator_void_pointer {
170 typedef typename detail::alloc_void_ptr<A>::type type;
171};
172
173namespace detail {
174
175template<class A, class = void>
176struct alloc_const_void_ptr {
177 typedef typename boost::pointer_traits<typename
178 boost::allocator_pointer<A>::type>::template
179 rebind_to<const void>::type type;
180};
181
182template<class A>
183struct alloc_const_void_ptr<A,
184 typename alloc_void<typename A::const_void_pointer>::type> {
185 typedef typename A::const_void_pointer type;
186};
187
188} /* detail */
189
190template<class A>
191struct allocator_const_void_pointer {
192 typedef typename detail::alloc_const_void_ptr<A>::type type;
193};
194
195namespace detail {
196
197template<class A, class = void>
198struct alloc_diff_type {
199 typedef typename boost::pointer_traits<typename
200 boost::allocator_pointer<A>::type>::difference_type type;
201};
202
203template<class A>
204struct alloc_diff_type<A,
205 typename alloc_void<typename A::difference_type>::type> {
206 typedef typename A::difference_type type;
207};
208
209} /* detail */
210
211template<class A>
212struct allocator_difference_type {
213 typedef typename detail::alloc_diff_type<A>::type type;
214};
215
216namespace detail {
217
218#if defined(BOOST_NO_CXX11_ALLOCATOR)
219template<class A, class = void>
220struct alloc_size_type {
221 typedef std::size_t type;
222};
223#else
224template<class A, class = void>
225struct alloc_size_type {
226 typedef typename std::make_unsigned<typename
227 boost::allocator_difference_type<A>::type>::type type;
228};
229#endif
230
231template<class A>
232struct alloc_size_type<A,
233 typename alloc_void<typename A::size_type>::type> {
234 typedef typename A::size_type type;
235};
236
237} /* detail */
238
239template<class A>
240struct allocator_size_type {
241 typedef typename detail::alloc_size_type<A>::type type;
242};
243
244namespace detail {
245
246#if defined(BOOST_NO_CXX11_ALLOCATOR)
247template<bool V>
248struct alloc_bool {
249 typedef bool value_type;
250 typedef alloc_bool type;
251
252 static const bool value = V;
253
254 operator bool() const BOOST_NOEXCEPT {
255 return V;
256 }
257
258 bool operator()() const BOOST_NOEXCEPT {
259 return V;
260 }
261};
262
263template<bool V>
264const bool alloc_bool<V>::value;
265
266typedef alloc_bool<false> alloc_false;
267#else
268typedef std::false_type alloc_false;
269#endif
270
271template<class A, class = void>
272struct alloc_pocca {
273 typedef alloc_false type;
274};
275
276template<class A>
277struct alloc_pocca<A,
278 typename alloc_void<typename
279 A::propagate_on_container_copy_assignment>::type> {
280 typedef typename A::propagate_on_container_copy_assignment type;
281};
282
283} /* detail */
284
285template<class A, class = void>
286struct allocator_propagate_on_container_copy_assignment {
287 typedef typename detail::alloc_pocca<A>::type type;
288};
289
290namespace detail {
291
292template<class A, class = void>
293struct alloc_pocma {
294 typedef alloc_false type;
295};
296
297template<class A>
298struct alloc_pocma<A,
299 typename alloc_void<typename
300 A::propagate_on_container_move_assignment>::type> {
301 typedef typename A::propagate_on_container_move_assignment type;
302};
303
304} /* detail */
305
306template<class A>
307struct allocator_propagate_on_container_move_assignment {
308 typedef typename detail::alloc_pocma<A>::type type;
309};
310
311namespace detail {
312
313template<class A, class = void>
314struct alloc_pocs {
315 typedef alloc_false type;
316};
317
318template<class A>
319struct alloc_pocs<A,
320 typename alloc_void<typename A::propagate_on_container_swap>::type> {
321 typedef typename A::propagate_on_container_swap type;
322};
323
324} /* detail */
325
326template<class A>
327struct allocator_propagate_on_container_swap {
328 typedef typename detail::alloc_pocs<A>::type type;
329};
330
331namespace detail {
332
333#if !defined(BOOST_NO_CXX11_ALLOCATOR)
334template<class A, class = void>
335struct alloc_equal {
336 typedef typename std::is_empty<A>::type type;
337};
338#elif defined(BOOST_DETAIL_ALLOC_EMPTY)
339template<class A, class = void>
340struct alloc_equal {
341 typedef alloc_bool<BOOST_DETAIL_ALLOC_EMPTY(A)> type;
342};
343#else
344template<class A, class = void>
345struct alloc_equal {
346 typedef alloc_false type;
347};
348#endif
349
350template<class A>
351struct alloc_equal<A,
352 typename alloc_void<typename A::is_always_equal>::type> {
353 typedef typename A::is_always_equal type;
354};
355
356} /* detail */
357
358template<class A>
359struct allocator_is_always_equal {
360 typedef typename detail::alloc_equal<A>::type type;
361};
362
363template<class A>
364inline typename allocator_pointer<A>::type
365allocator_allocate(A& a, typename allocator_size_type<A>::type n)
366{
367 return a.allocate(n);
368}
369
370template<class A>
371inline void
372allocator_deallocate(A& a, typename allocator_pointer<A>::type p,
373 typename allocator_size_type<A>::type n)
374{
375 a.deallocate(p, n);
376}
377
378#if defined(BOOST_NO_CXX11_ALLOCATOR)
379template<class A>
380inline typename allocator_pointer<A>::type
381allocator_allocate(A& a, typename allocator_size_type<A>::type n,
382 typename allocator_const_void_pointer<A>::type h)
383{
384 return a.allocate(n, h);
385}
386#else
387namespace detail {
388
389template<class>
390struct alloc_no {
391 char x, y;
392};
393
394template<class A>
395class alloc_has_allocate {
396 template<class O>
397 static auto check(int)
398 -> alloc_no<decltype(std::declval<O&>().allocate(std::declval<typename
399 boost::allocator_size_type<A>::type>(), std::declval<typename
400 boost::allocator_const_void_pointer<A>::type>()))>;
401
402 template<class>
403 static char check(long);
404
405public:
406 BOOST_STATIC_CONSTEXPR bool value = sizeof(check<A>(0)) > 1;
407};
408
409} /* detail */
410
411template<class A>
412inline typename std::enable_if<detail::alloc_has_allocate<A>::value,
413 typename allocator_pointer<A>::type>::type
414allocator_allocate(A& a, typename allocator_size_type<A>::type n,
415 typename allocator_const_void_pointer<A>::type h)
416{
417 return a.allocate(n, h);
418}
419
420template<class A>
421inline typename std::enable_if<!detail::alloc_has_allocate<A>::value,
422 typename allocator_pointer<A>::type>::type
423allocator_allocate(A& a, typename allocator_size_type<A>::type n,
424 typename allocator_const_void_pointer<A>::type)
425{
426 return a.allocate(n);
427}
428#endif
429
430namespace detail {
431
432#if defined(BOOST_NO_CXX11_ALLOCATOR)
433template<class A, class = void>
434struct alloc_has_construct {
435 BOOST_STATIC_CONSTEXPR bool value = false;
436};
437
438template<class A>
439struct alloc_has_construct<A,
440 typename alloc_void<typename A::_default_construct_destroy>::type> {
441 BOOST_STATIC_CONSTEXPR bool value = true;
442};
443#else
444template<class A, class T, class... Args>
445class alloc_has_construct {
446 template<class O>
447 static auto check(int)
448 -> alloc_no<decltype(std::declval<O&>().construct(std::declval<T*>(),
449 std::declval<Args&&>()...))>;
450
451 template<class>
452 static char check(long);
453
454public:
455 BOOST_STATIC_CONSTEXPR bool value = sizeof(check<A>(0)) > 1;
456};
457#endif
458
459template<bool, class = void>
460struct alloc_if { };
461
462template<class T>
463struct alloc_if<true, T> {
464 typedef T type;
465};
466
467} /* detail */
468
469#if defined(BOOST_NO_CXX11_ALLOCATOR)
470template<class A, class T>
471inline typename detail::alloc_if<detail::alloc_has_construct<A>::value>::type
472allocator_construct(A& a, T* p)
473{
474 a.construct(p);
475}
476
477template<class A, class T>
478inline typename detail::alloc_if<!detail::alloc_has_construct<A>::value>::type
479allocator_construct(A&, T* p)
480{
481 ::new((void*)p) T();
482}
483
484#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
485#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
486template<class A, class T, class V, class... Args>
487inline void
488allocator_construct(A&, T* p, V&& v, Args&&... args)
489{
490 ::new((void*)p) T(std::forward<V>(v), std::forward<Args>(args)...);
491}
492#else
493template<class A, class T, class V>
494inline void
495allocator_construct(A&, T* p, V&& v)
496{
497 ::new((void*)p) T(std::forward<V>(v));
498}
499#endif
500#else
501template<class A, class T, class V>
502inline void
503allocator_construct(A&, T* p, const V& v)
504{
505 ::new((void*)p) T(v);
506}
507
508template<class A, class T, class V>
509inline void
510allocator_construct(A&, T* p, V& v)
511{
512 ::new((void*)p) T(v);
513}
514#endif
515#else
516template<class A, class T, class... Args>
517inline typename std::enable_if<detail::alloc_has_construct<A, T,
518 Args...>::value>::type
519allocator_construct(A& a, T* p, Args&&... args)
520{
521 a.construct(p, std::forward<Args>(args)...);
522}
523
524template<class A, class T, class... Args>
525inline typename std::enable_if<!detail::alloc_has_construct<A, T,
526 Args...>::value>::type
527allocator_construct(A&, T* p, Args&&... args)
528{
529 ::new((void*)p) T(std::forward<Args>(args)...);
530}
531#endif
532
533namespace detail {
534
535#if defined(BOOST_NO_CXX11_ALLOCATOR)
536template<class A, class, class = void>
537struct alloc_has_destroy {
538 BOOST_STATIC_CONSTEXPR bool value = false;
539};
540
541template<class A, class T>
542struct alloc_has_destroy<A, T,
543 typename alloc_void<typename A::_default_construct_destroy>::type> {
544 BOOST_STATIC_CONSTEXPR bool value = true;
545};
546#else
547template<class A, class T>
548class alloc_has_destroy {
549 template<class O>
550 static auto check(int)
551 -> alloc_no<decltype(std::declval<O&>().destroy(std::declval<T*>()))>;
552
553 template<class>
554 static char check(long);
555
556public:
557 BOOST_STATIC_CONSTEXPR bool value = sizeof(check<A>(0)) > 1;
558};
559#endif
560
561} /* detail */
562
563template<class A, class T>
564inline typename detail::alloc_if<detail::alloc_has_destroy<A, T>::value>::type
565allocator_destroy(A& a, T* p)
566{
567 a.destroy(p);
568}
569
570template<class A, class T>
571inline typename detail::alloc_if<!detail::alloc_has_destroy<A, T>::value>::type
572allocator_destroy(A&, T* p)
573{
574 p->~T();
575 (void)p;
576}
577
578namespace detail {
579
580#if defined(BOOST_NO_CXX11_ALLOCATOR)
581template<class T, T>
582struct alloc_no {
583 char x, y;
584};
585
586template<class A>
587class alloc_has_max_size {
588 template<class O>
589 static alloc_no<typename boost::allocator_size_type<O>::type(O::*)(),
590 &O::max_size> check(int);
591
592 template<class O>
593 static alloc_no<typename boost::allocator_size_type<O>::type(O::*)() const,
594 &O::max_size> check(int);
595
596 template<class O>
597 static alloc_no<typename boost::allocator_size_type<O>::type(*)(),
598 &O::max_size> check(int);
599
600 template<class>
601 static char check(long);
602
603public:
604 BOOST_STATIC_CONSTEXPR bool value = sizeof(check<A>(0)) > 1;
605};
606#else
607template<class A>
608class alloc_has_max_size {
609 template<class O>
610 static auto check(int)
611 -> alloc_no<decltype(std::declval<const O&>().max_size())>;
612
613 template<class>
614 static char check(long);
615
616public:
617 BOOST_STATIC_CONSTEXPR bool value = sizeof(check<A>(0)) > 1;
618};
619#endif
620
621} /* detail */
622
623template<class A>
624inline typename detail::alloc_if<detail::alloc_has_max_size<A>::value,
625 typename allocator_size_type<A>::type>::type
626allocator_max_size(const A& a) BOOST_NOEXCEPT
627{
628 return a.max_size();
629}
630
631template<class A>
632inline typename detail::alloc_if<!detail::alloc_has_max_size<A>::value,
633 typename allocator_size_type<A>::type>::type
634allocator_max_size(const A&) BOOST_NOEXCEPT
635{
636 return (std::numeric_limits<typename
637 allocator_size_type<A>::type>::max)() /
638 sizeof(typename allocator_value_type<A>::type);
639}
640
641namespace detail {
642
643#if defined(BOOST_NO_CXX11_ALLOCATOR)
644template<class A>
645class alloc_has_soccc {
646 template<class O>
647 static alloc_no<O(O::*)(), &O::select_on_container_copy_construction>
648 check(int);
649
650 template<class O>
651 static alloc_no<O(O::*)() const, &O::select_on_container_copy_construction>
652 check(int);
653
654 template<class O>
655 static alloc_no<O(*)(), &O::select_on_container_copy_construction>
656 check(int);
657
658 template<class>
659 static char check(long);
660
661public:
662 BOOST_STATIC_CONSTEXPR bool value = sizeof(check<A>(0)) > 1;
663};
664#else
665template<class A>
666class alloc_has_soccc {
667 template<class O>
668 static auto check(int) -> alloc_no<decltype(std::declval<const
669 O&>().select_on_container_copy_construction())>;
670
671 template<class>
672 static char check(long);
673
674public:
675 BOOST_STATIC_CONSTEXPR bool value = sizeof(check<A>(0)) > 1;
676};
677#endif
678
679} /* detail */
680
681template<class A>
682inline typename detail::alloc_if<detail::alloc_has_soccc<A>::value, A>::type
683allocator_select_on_container_copy_construction(const A& a)
684{
685 return a.select_on_container_copy_construction();
686}
687
688template<class A>
689inline typename detail::alloc_if<!detail::alloc_has_soccc<A>::value, A>::type
690allocator_select_on_container_copy_construction(const A& a)
691{
692 return a;
693}
694
695template<class A, class T>
696inline void
697allocator_destroy_n(A& a, T* p, std::size_t n)
698{
699 while (n > 0) {
700 boost::allocator_destroy(a, p + --n);
701 }
702}
703
704namespace detail {
705
706template<class A, class T>
707class alloc_destroyer {
708public:
709 alloc_destroyer(A& a, T* p) BOOST_NOEXCEPT
710 : a_(a), p_(p), n_(0) { }
711
712 ~alloc_destroyer() {
713 boost::allocator_destroy_n(a_, p_, n_);
714 }
715
716 std::size_t& size() BOOST_NOEXCEPT {
717 return n_;
718 }
719
720private:
721 alloc_destroyer(const alloc_destroyer&);
722 alloc_destroyer& operator=(const alloc_destroyer&);
723
724 A& a_;
725 T* p_;
726 std::size_t n_;
727};
728
729} /* detail */
730
731template<class A, class T>
732inline void
733allocator_construct_n(A& a, T* p, std::size_t n)
734{
735 detail::alloc_destroyer<A, T> d(a, p);
736 for (std::size_t& i = d.size(); i < n; ++i) {
737 boost::allocator_construct(a, p + i);
738 }
739 d.size() = 0;
740}
741
742template<class A, class T>
743inline void
744allocator_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m)
745{
746 detail::alloc_destroyer<A, T> d(a, p);
747 for (std::size_t& i = d.size(); i < n; ++i) {
748 boost::allocator_construct(a, p + i, l[i % m]);
749 }
750 d.size() = 0;
751}
752
753template<class A, class T, class I>
754inline void
755allocator_construct_n(A& a, T* p, std::size_t n, I b)
756{
757 detail::alloc_destroyer<A, T> d(a, p);
758 for (std::size_t& i = d.size(); i < n; void(++i), void(++b)) {
759 boost::allocator_construct(a, p + i, *b);
760 }
761 d.size() = 0;
762}
763
764#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
765template<class A>
766using allocator_value_type_t = typename allocator_value_type<A>::type;
767
768template<class A>
769using allocator_pointer_t = typename allocator_pointer<A>::type;
770
771template<class A>
772using allocator_const_pointer_t = typename allocator_const_pointer<A>::type;
773
774template<class A>
775using allocator_void_pointer_t = typename allocator_void_pointer<A>::type;
776
777template<class A>
778using allocator_const_void_pointer_t =
779 typename allocator_const_void_pointer<A>::type;
780
781template<class A>
782using allocator_difference_type_t =
783 typename allocator_difference_type<A>::type;
784
785template<class A>
786using allocator_size_type_t = typename allocator_size_type<A>::type;
787
788template<class A>
789using allocator_propagate_on_container_copy_assignment_t =
790 typename allocator_propagate_on_container_copy_assignment<A>::type;
791
792template<class A>
793using allocator_propagate_on_container_move_assignment_t =
794 typename allocator_propagate_on_container_move_assignment<A>::type;
795
796template<class A>
797using allocator_propagate_on_container_swap_t =
798 typename allocator_propagate_on_container_swap<A>::type;
799
800template<class A>
801using allocator_is_always_equal_t =
802 typename allocator_is_always_equal<A>::type;
803
804template<class A, class T>
805using allocator_rebind_t = typename allocator_rebind<A, T>::type;
806#endif
807
808} /* boost */
809
810#if defined(_MSC_VER)
811#pragma warning(pop)
812#endif
813#if defined(_STL_RESTORE_DEPRECATED_WARNING)
814_STL_RESTORE_DEPRECATED_WARNING
815#endif
816#if defined(_LIBCPP_SUPPRESS_DEPRECATED_POP)
817_LIBCPP_SUPPRESS_DEPRECATED_POP
818#endif
819
820#endif
821