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