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

source code of boost/libs/core/include/boost/core/allocator_access.hpp