1 /* Copyright 2003-2020 Joaquin M Lopez Munoz. 2 * Distributed under the Boost Software License, Version 1.0. 3 * (See accompanying file LICENSE_1_0.txt or copy at 4 * http://www.boost.org/LICENSE_1_0.txt) 5 * 6 * See http://www.boost.org/libs/multi_index for library home page. 7 */ 8 9 #ifndef BOOST_MULTI_INDEX_DETAIL_ALLOCATOR_TRAITS_HPP 10 #define BOOST_MULTI_INDEX_DETAIL_ALLOCATOR_TRAITS_HPP 11 12 #if defined(_MSC_VER) 13 #pragma once 14 #endif 15 16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ 17 18 #if !defined(BOOST_NO_CXX11_ALLOCATOR) 19 #include <boost/type_traits/is_empty.hpp> 20 #include <memory> 21 #else 22 #include <boost/detail/workaround.hpp> 23 #include <boost/move/core.hpp> 24 #include <boost/move/utility_core.hpp> 25 #include <boost/multi_index/detail/vartempl_support.hpp> 26 #include <boost/type_traits/integral_constant.hpp> 27 #include <boost/type_traits/is_empty.hpp> 28 #include <new> 29 #endif 30 31 namespace boost{ 32 33 namespace multi_index{ 34 35 namespace detail{ 36 37 /* poor man's replacement of std::allocator_traits */ 38 39 #if !defined(BOOST_NO_CXX11_ALLOCATOR) 40 41 template<typename T> struct void_helper{typedef void type;}; 42 43 template<typename Allocator,typename=void> 44 struct allocator_is_always_equal:boost::is_empty<Allocator>{}; 45 46 template<typename Allocator> 47 struct allocator_is_always_equal< 48 Allocator, 49 typename void_helper< 50 typename std::allocator_traits<Allocator>::is_always_equal 51 >::type 52 >:std::allocator_traits<Allocator>::is_always_equal{}; 53 54 template<typename Allocator> 55 struct allocator_traits:std::allocator_traits<Allocator> 56 { 57 /* wrap std::allocator_traits alias templates for use in C++03 codebase */ 58 59 typedef std::allocator_traits<Allocator> super; 60 61 /* pre-C++17 compatibilty */ 62 63 typedef allocator_is_always_equal<Allocator> is_always_equal; 64 65 template<typename T> 66 struct rebind_alloc 67 { 68 typedef typename super::template rebind_alloc<T> type; 69 }; 70 71 template<typename T> 72 struct rebind_traits 73 { 74 typedef typename super::template rebind_traits<T> type; 75 }; 76 }; 77 78 #else 79 80 /* not a full std::allocator_traits rewrite (not needed) */ 81 82 template<typename Allocator> 83 struct allocator_traits 84 { 85 typedef Allocator allocator_type; 86 typedef typename Allocator::value_type value_type; 87 typedef typename Allocator::pointer pointer; 88 typedef typename Allocator::const_pointer const_pointer; 89 90 /* [const_]void_pointer not provided as boost::pointer_traits's 91 * rebind_to has been seen to fail with things like 92 * boost::interprocess::offset_ptr in relatively old environments. 93 */ 94 95 typedef typename Allocator::difference_type difference_type; 96 typedef typename Allocator::size_type size_type; 97 98 typedef boost::false_type propagate_on_container_copy_assignment; 99 typedef boost::false_type propagate_on_container_move_assignment; 100 typedef boost::false_type propagate_on_container_swap; 101 typedef boost::is_empty<Allocator> is_always_equal; 102 103 template<typename T> 104 struct rebind_alloc 105 { 106 typedef typename Allocator::template rebind<T>::other type; 107 }; 108 109 template<typename T> 110 struct rebind_traits 111 { 112 typedef allocator_traits<typename rebind_alloc<T>::type> type; 113 }; 114 115 static pointer allocate(Allocator& a,size_type n){return a.allocate(n);} 116 static pointer allocate(Allocator& a,size_type n,const_pointer p) 117 /* should've been const_void_pointer p */ 118 {return a.allocate(n,p);} 119 static void deallocate(Allocator& a,pointer p,size_type n) 120 {a.deallocate(p,n);} 121 template<typename T> 122 static void construct(Allocator&,T* p,const T& x) 123 {::new (static_cast<void*>(p)) T(x);} 124 template<typename T> 125 static void construct(Allocator&,T* p,BOOST_RV_REF(T) x) 126 {::new (static_cast<void*>(p)) T(boost::move(x));} 127 128 template<typename T,BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK> 129 static void construct(Allocator&,T* p,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK) 130 { 131 vartempl_placement_new(p,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK); 132 } 133 134 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500)) 135 /* MSVC issues spurious warnings about unreferencend formal parameters in 136 * destroy<T> when T is a class with trivial dtor. 137 */ 138 139 #pragma warning(push) 140 #pragma warning(disable:4100) 141 #endif 142 143 template<typename T> 144 static void destroy(Allocator&,T* p){p->~T();} 145 146 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500)) 147 #pragma warning(pop) 148 #endif 149 150 static size_type max_size(Allocator& a)BOOST_NOEXCEPT{return a.max_size();} 151 152 static Allocator select_on_container_copy_construction(const Allocator& a) 153 { 154 return a; 155 } 156 }; 157 158 #endif 159 160 template<typename Allocator,typename T> 161 struct rebind_alloc_for 162 { 163 typedef typename allocator_traits<Allocator>:: 164 template rebind_alloc<T>::type type; 165 }; 166 167 } /* namespace multi_index::detail */ 168 169 } /* namespace multi_index */ 170 171 } /* namespace boost */ 172 173 #endif 174