From 0c9675cf56553f83577e315c6625a8e7c2c7c13d Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 6 Dec 2021 16:42:17 -0500 Subject: [PATCH] Add partial C++03 support for C++11 allocator model --- include/boost/core/allocator_access.hpp | 273 ++++++++++++++---------- 1 file changed, 162 insertions(+), 111 deletions(-) diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 1fee1e6..fab7474 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -9,16 +9,28 @@ Distributed under the Boost Software License, Version 1.0. #define BOOST_CORE_ALLOCATOR_ACCESS_HPP #include -#if !defined(BOOST_NO_CXX11_ALLOCATOR) #include #include +#include +#if !defined(BOOST_NO_CXX11_ALLOCATOR) #include #endif -#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #include #endif +#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 40300) +#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#elif defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500) +#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) +#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#elif defined(BOOST_CLANG) && !defined(__CUDACC__) +#if __has_feature(is_empty) +#define BOOST_DETAIL_ALLOC_HAS_IS_EMTPY +#endif +#endif + #if defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH) _LIBCPP_SUPPRESS_DEPRECATED_PUSH #endif @@ -37,12 +49,6 @@ struct allocator_value_type { typedef typename A::value_type type; }; -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_pointer { - typedef typename A::pointer type; -}; -#else namespace detail { template @@ -67,14 +73,7 @@ template struct allocator_pointer { typedef typename detail::alloc_ptr::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_const_pointer { - typedef typename A::const_pointer type; -}; -#else namespace detail { template @@ -96,23 +95,34 @@ template struct allocator_const_pointer { typedef typename detail::alloc_const_ptr::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_rebind { - typedef typename A::template rebind::other type; -}; -#else namespace detail { template struct alloc_to { }; +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +template class A, class T, class U> +struct alloc_to, T> { + typedef A type; +}; + +template class A, class T, class U, class V> +struct alloc_to, T> { + typedef A type; +}; + +template class A, class T, class U, class V1, + class V2> +struct alloc_to, T> { + typedef A type; +}; +#else template class A, class T, class U, class... V> struct alloc_to, T> { typedef A type; }; +#endif template struct alloc_rebind { @@ -131,15 +141,7 @@ template struct allocator_rebind { typedef typename detail::alloc_rebind::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_void_pointer { - typedef typename allocator_pointer::type>::type type; -}; -#else namespace detail { template @@ -161,15 +163,7 @@ template struct allocator_void_pointer { typedef typename detail::alloc_void_ptr::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_const_void_pointer { - typedef typename allocator_const_pointer::type>::type type; -}; -#else namespace detail { template @@ -191,14 +185,7 @@ template struct allocator_const_void_pointer { typedef typename detail::alloc_const_void_ptr::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_difference_type { - typedef typename A::difference_type type; -}; -#else namespace detail { template @@ -219,21 +206,21 @@ template struct allocator_difference_type { typedef typename detail::alloc_diff_type::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_size_type { - typedef typename A::size_type type; -}; -#else namespace detail { +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct alloc_size_type { + typedef std::size_t type; +}; +#else template struct alloc_size_type { typedef typename std::make_unsigned::type>::type type; }; +#endif template struct alloc_size_type struct allocator_size_type { typedef typename detail::alloc_size_type::type type; }; -#endif + +namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) -namespace detail { +template +struct alloc_bool { + typedef bool value_type; + typedef alloc_bool type; -struct alloc_false { - BOOST_STATIC_CONSTEXPR bool value = false; + static const bool value = V; + + operator bool() const BOOST_NOEXCEPT { + return V; + } + + bool operator()() const BOOST_NOEXCEPT { + return V; + } }; -} /* detail */ +template +const bool alloc_bool::value; -template -struct allocator_propagate_on_container_copy_assignment { - typedef detail::alloc_false type; -}; +typedef alloc_bool alloc_false; #else -namespace detail { +typedef std::false_type alloc_false; +#endif template struct alloc_pocca { - typedef std::false_type type; + typedef alloc_false type; }; template @@ -283,19 +280,12 @@ template struct allocator_propagate_on_container_copy_assignment { typedef typename detail::alloc_pocca::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_propagate_on_container_move_assignment { - typedef detail::alloc_false type; -}; -#else namespace detail { template struct alloc_pocma { - typedef std::false_type type; + typedef alloc_false type; }; template @@ -311,19 +301,12 @@ template struct allocator_propagate_on_container_move_assignment { typedef typename detail::alloc_pocma::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_propagate_on_container_swap { - typedef detail::alloc_false type; -}; -#else namespace detail { template struct alloc_pocs { - typedef std::false_type type; + typedef alloc_false type; }; template @@ -338,20 +321,25 @@ template struct allocator_propagate_on_container_swap { typedef typename detail::alloc_pocs::type type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_is_always_equal { - typedef detail::alloc_false type; -}; -#else namespace detail { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct alloc_equal { typedef typename std::is_empty::type type; }; +#elif defined(BOOST_DETAIL_ALLOC_HAS_IS_EMTPY) +template +struct alloc_equal { + typedef alloc_bool<__is_empty(A)> type; +}; +#else +template +struct alloc_equal { + typedef alloc_false type; +}; +#endif template struct alloc_equal struct allocator_is_always_equal { typedef typename detail::alloc_equal::type type; }; -#endif template inline typename allocator_pointer::type @@ -551,20 +538,46 @@ allocator_destroy(A&, T* p) } #endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -inline typename allocator_size_type::type -allocator_max_size(const A& a) BOOST_NOEXCEPT -{ - return a.max_size(); -} -#else namespace detail { +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template::type(A::*)()> +struct alloc_max_size { + char one, two; +}; + +template::type(A::*)() const> +struct alloc_max_size_const { + char one, two; +}; + +template::type(*)()> +struct alloc_max_size_static { + char one, two; +}; + template class alloc_has_max_size { template - static auto check(int) -> decltype(std::declval().max_size()); + static alloc_max_size check(int); + + template + static alloc_max_size_const check(int); + + template + static alloc_max_size_static check(int); + + template + static char check(long); + +public: + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) != 1; +}; +#else +template +class alloc_has_max_size { + template + static auto check(int) -> decltype(std::declval().max_size()); template static alloc_none check(long); @@ -573,11 +586,20 @@ public: BOOST_STATIC_CONSTEXPR bool value = !std::is_same(0)), alloc_none>::value; }; +#endif + +template +struct alloc_if { }; + +template +struct alloc_if { + typedef T type; +}; } /* detail */ template -inline typename std::enable_if::value, +inline typename detail::alloc_if::value, typename allocator_size_type::type>::type allocator_max_size(const A& a) BOOST_NOEXCEPT { @@ -585,7 +607,7 @@ allocator_max_size(const A& a) BOOST_NOEXCEPT } template -inline typename std::enable_if::value, +inline typename detail::alloc_if::value, typename allocator_size_type::type>::type allocator_max_size(const A&) BOOST_NOEXCEPT { @@ -593,23 +615,52 @@ allocator_max_size(const A&) BOOST_NOEXCEPT allocator_size_type::type>::max)() / sizeof(typename allocator_value_type::type); } -#endif + +namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) -template -inline A -allocator_select_on_container_copy_construction(const A& a) -{ - return a; -} -#else -namespace detail { +template +struct alloc_soccc { + char one, two; +}; + +template +struct alloc_soccc_const { + char one, two; +}; + +template +struct alloc_soccc_static { + char one, two; +}; +template +class alloc_has_soccc { + template + static alloc_soccc + check(int); + + template + static alloc_soccc_const + check(int); + + template + static alloc_soccc_static + check(int); + + template + static char check(long); + +public: + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) != 1; +}; +#else template class alloc_has_soccc { template static auto check(int) - -> decltype(std::declval().select_on_container_copy_construction()); + -> decltype(std::declval().select_on_container_copy_construction()); template static alloc_none check(long); @@ -618,23 +669,23 @@ public: BOOST_STATIC_CONSTEXPR bool value = !std::is_same(0)), alloc_none>::value; }; +#endif } /* detail */ template -inline typename std::enable_if::value, A>::type +inline typename detail::alloc_if::value, A>::type allocator_select_on_container_copy_construction(const A& a) { return a.select_on_container_copy_construction(); } template -inline typename std::enable_if::value, A>::type +inline typename detail::alloc_if::value, A>::type allocator_select_on_container_copy_construction(const A& a) { return a; } -#endif #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template