Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / container / allocator_traits.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Pablo Halpern 2009. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 //////////////////////////////////////////////////////////////////////////////
8 //
9 // (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
10 // Software License, Version 1.0. (See accompanying file
11 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12 //
13 // See http://www.boost.org/libs/container for documentation.
14 //
15 //////////////////////////////////////////////////////////////////////////////
16
17 #ifndef BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
18 #define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
19
20 #if defined(_MSC_VER)
21 #  pragma once
22 #endif
23
24 #include <boost/container/detail/config_begin.hpp>
25 #include <boost/container/detail/workaround.hpp>
26 #include <boost/container/container_fwd.hpp>
27 #include <boost/intrusive/pointer_traits.hpp>
28 #include <boost/intrusive/detail/memory_util.hpp>
29 #include <boost/container/detail/memory_util.hpp>
30 #include <boost/container/detail/mpl.hpp>
31 #include <boost/container/detail/placement_new.hpp>
32 #include <boost/move/utility_core.hpp>
33
34 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
35 #include <boost/container/detail/preprocessor.hpp>
36 #endif
37
38
39
40 namespace boost {
41 namespace container {
42 namespace allocator_traits_detail {
43
44 }
45
46 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
47
48 namespace container_detail {
49
50 //workaround needed for C++03 compilers with no construct()
51 //supporting rvalue references
52 template<class A>
53 struct is_std_allocator
54 {  static const bool value = false; };
55
56 template<class T>
57 struct is_std_allocator< std::allocator<T> >
58 {  static const bool value = true; };
59
60 }  //namespace container_detail {
61
62 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
63
64 //! The class template allocator_traits supplies a uniform interface to all allocator types.
65 //! This class is a C++03-compatible implementation of std::allocator_traits
66 template <typename Alloc>
67 struct allocator_traits
68 {
69    //allocator_type
70    typedef Alloc allocator_type;
71    //value_type
72    typedef typename Alloc::value_type         value_type;
73
74    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
75       //! Alloc::pointer if such a type exists; otherwise, value_type*
76       //!
77       typedef unspecified pointer;
78       //! Alloc::const_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<const
79       //!
80       typedef see_documentation const_pointer;
81       //! Non-standard extension
82       //! Alloc::reference if such a type exists; otherwise, value_type&
83       typedef see_documentation reference;
84       //! Non-standard extension
85       //! Alloc::const_reference if such a type exists ; otherwise, const value_type&
86       typedef see_documentation const_reference;
87       //! Alloc::void_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<void>.
88       //!
89       typedef see_documentation void_pointer;
90       //! Alloc::const_void_pointer if such a type exists ; otherwis e, pointer_traits<pointer>::rebind<const
91       //!
92       typedef see_documentation const_void_pointer;
93       //! Alloc::difference_type if such a type exists ; otherwise, pointer_traits<pointer>::difference_type.
94       //!
95       typedef see_documentation difference_type;
96       //! Alloc::size_type if such a type exists ; otherwise, make_unsigned<difference_type>::type
97       //!
98       typedef see_documentation size_type;
99       //! Alloc::propagate_on_container_copy_assignment if such a type exists, otherwise an integral_constant
100       //! type with internal constant static member <code>value</code> == false.
101       typedef see_documentation propagate_on_container_copy_assignment;
102       //! Alloc::propagate_on_container_move_assignment if such a type exists, otherwise an integral_constant
103       //! type with internal constant static member <code>value</code> == false.
104       typedef see_documentation propagate_on_container_move_assignment;
105       //! Alloc::propagate_on_container_swap if such a type exists, otherwise an integral_constant
106       //! type with internal constant static member <code>value</code> == false.
107       typedef see_documentation propagate_on_container_swap;
108       //! Defines an allocator: Alloc::rebind<T>::other if such a type exists; otherwise, Alloc<T, Args>
109       //! if Alloc is a class template instantiation of the form Alloc<U, Args>, where Args is zero or
110       //! more type arguments ; otherwise, the instantiation of rebind_alloc is ill-formed.
111       //!
112       //! In C++03 compilers <code>rebind_alloc</code> is a struct derived from an allocator
113       //! deduced by previously detailed rules.
114       template <class T> using rebind_alloc = see_documentation;
115
116       //! In C++03 compilers <code>rebind_traits</code> is a struct derived from
117       //! <code>allocator_traits<OtherAlloc></code>, where <code>OtherAlloc</code> is
118       //! the allocator deduced by rules explained in <code>rebind_alloc</code>.
119       template <class T> using rebind_traits = allocator_traits<rebind_alloc<T> >;
120
121       //! Non-standard extension: Portable allocator rebind for C++03 and C++11 compilers.
122       //! <code>type</code> is an allocator related to Alloc deduced deduced by rules explained in <code>rebind_alloc</code>.
123       template <class T>
124       struct portable_rebind_alloc
125       {  typedef see_documentation type;  };
126    #else
127       //pointer
128       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
129          pointer, value_type*)
130             pointer;
131       //const_pointer
132       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc,
133          const_pointer, typename boost::intrusive::pointer_traits<pointer>::template
134             rebind_pointer<const value_type>)
135                const_pointer;
136       //reference
137       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
138          reference, typename container_detail::unvoid<value_type>::type&)
139             reference;
140       //const_reference
141       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
142          const_reference, const typename container_detail::unvoid<value_type>::type&)
143                const_reference;
144       //void_pointer
145       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc,
146          void_pointer, typename boost::intrusive::pointer_traits<pointer>::template
147             rebind_pointer<void>)
148                void_pointer;
149       //const_void_pointer
150       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc,
151          const_void_pointer, typename boost::intrusive::pointer_traits<pointer>::template
152             rebind_pointer<const void>)
153                const_void_pointer;
154       //difference_type
155       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
156          difference_type, std::ptrdiff_t)
157             difference_type;
158       //size_type
159       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
160          size_type, std::size_t)
161             size_type;
162       //propagate_on_container_copy_assignment
163       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
164          propagate_on_container_copy_assignment, container_detail::false_type)
165             propagate_on_container_copy_assignment;
166       //propagate_on_container_move_assignment
167       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
168          propagate_on_container_move_assignment, container_detail::false_type)
169             propagate_on_container_move_assignment;
170       //propagate_on_container_swap
171       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
172          propagate_on_container_swap, container_detail::false_type)
173             propagate_on_container_swap;
174
175       #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
176          //C++11
177          template <typename T> using rebind_alloc  = typename boost::intrusive::pointer_rebind<Alloc, T>::type;
178          template <typename T> using rebind_traits = allocator_traits< rebind_alloc<T> >;
179       #else    // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
180          //Some workaround for C++03 or C++11 compilers with no template aliases
181          template <typename T>
182          struct rebind_alloc : boost::intrusive::pointer_rebind<Alloc,T>::type
183          {
184             typedef typename boost::intrusive::pointer_rebind<Alloc,T>::type Base;
185             #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
186             template <typename... Args>
187             rebind_alloc(BOOST_FWD_REF(Args)... args)
188                : Base(boost::forward<Args>(args)...)
189             {}
190             #else    // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
191             #define BOOST_PP_LOCAL_MACRO(n)                                                        \
192             BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
193             rebind_alloc(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _))                       \
194                : Base(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))                       \
195             {}                                                                                     \
196             //
197             #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
198             #include BOOST_PP_LOCAL_ITERATE()
199             #endif   // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
200          };
201
202          template <typename T>
203          struct rebind_traits
204             : allocator_traits<typename boost::intrusive::pointer_rebind<Alloc, T>::type>
205          {};
206       #endif   // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
207       template <class T>
208       struct portable_rebind_alloc
209       {  typedef typename boost::intrusive::pointer_rebind<Alloc, T>::type type;  };
210    #endif   //BOOST_CONTAINER_DOXYGEN_INVOKED
211
212    //! <b>Returns</b>: <code>a.allocate(n)</code>
213    //!
214    static pointer allocate(Alloc &a, size_type n)
215    {  return a.allocate(n);  }
216
217    //! <b>Returns</b>: <code>a.deallocate(p, n)</code>
218    //!
219    //! <b>Throws</b>: Nothing
220    static void deallocate(Alloc &a, pointer p, size_type n)
221    {  a.deallocate(p, n);  }
222
223    //! <b>Effects</b>: calls <code>a.allocate(n, p)</code> if that call is well-formed;
224    //! otherwise, invokes <code>a.allocate(n)</code>
225    static pointer allocate(Alloc &a, size_type n, const_void_pointer p)
226    {
227       const bool value = boost::container::container_detail::
228          has_member_function_callable_with_allocate
229             <Alloc, const size_type, const const_void_pointer>::value;
230       container_detail::bool_<value> flag;
231       return allocator_traits::priv_allocate(flag, a, n, p);
232    }
233
234    //! <b>Effects</b>: calls <code>a.destroy(p)</code> if that call is well-formed;
235    //! otherwise, invokes <code>p->~T()</code>.
236    template<class T>
237    static void destroy(Alloc &a, T*p) BOOST_CONTAINER_NOEXCEPT
238    {
239       typedef T* destroy_pointer;
240       const bool value = boost::container::container_detail::
241          has_member_function_callable_with_destroy
242             <Alloc, const destroy_pointer>::value;
243       container_detail::bool_<value> flag;
244       allocator_traits::priv_destroy(flag, a, p);
245    }
246
247    //! <b>Returns</b>: <code>a.max_size()</code> if that expression is well-formed; otherwise,
248    //! <code>numeric_limits<size_type>::max()</code>.
249    static size_type max_size(const Alloc &a) BOOST_CONTAINER_NOEXCEPT
250    {
251       const bool value = boost::container::container_detail::
252          has_member_function_callable_with_max_size
253             <const Alloc>::value;
254       container_detail::bool_<value> flag;
255       return allocator_traits::priv_max_size(flag, a);
256    }
257
258    //! <b>Returns</b>: <code>a.select_on_container_copy_construction()</code> if that expression is well-formed;
259    //! otherwise, a.
260    static
261    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
262    typename container_detail::if_c
263       <  boost::container::container_detail::
264                   has_member_function_callable_with_select_on_container_copy_construction
265                      <const Alloc>::value
266       , Alloc
267       , const Alloc &
268       >::type
269    #else
270    Alloc
271    #endif
272    select_on_container_copy_construction(const Alloc &a)
273    {
274       const bool value = boost::container::container_detail::
275          has_member_function_callable_with_select_on_container_copy_construction
276             <const Alloc>::value;
277       container_detail::bool_<value> flag;
278       return allocator_traits::priv_select_on_container_copy_construction(flag, a);
279    }
280
281    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
282       //! <b>Effects</b>: calls <code>a.construct(p, std::forward<Args>(args)...)</code> if that call is well-formed;
283       //! otherwise, invokes <code>::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code>
284       template <class T, class ...Args>
285       static void construct(Alloc & a, T* p, BOOST_FWD_REF(Args)... args)
286       {
287          container_detail::bool_<container_detail::is_std_allocator<Alloc>::value> flag;
288          allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...);
289       }
290    #endif
291    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
292    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
293       private:
294       static pointer priv_allocate(container_detail::true_type, Alloc &a, size_type n, const_void_pointer p)
295       {  return a.allocate(n, p);  }
296
297       static pointer priv_allocate(container_detail::false_type, Alloc &a, size_type n, const_void_pointer)
298       {  return allocator_traits::allocate(a, n);  }
299
300       template<class T>
301       static void priv_destroy(container_detail::true_type, Alloc &a, T* p) BOOST_CONTAINER_NOEXCEPT
302       {  a.destroy(p);  }
303
304       template<class T>
305       static void priv_destroy(container_detail::false_type, Alloc &, T* p) BOOST_CONTAINER_NOEXCEPT
306       {  p->~T(); (void)p;  }
307
308       static size_type priv_max_size(container_detail::true_type, const Alloc &a) BOOST_CONTAINER_NOEXCEPT
309       {  return a.max_size();  }
310
311       static size_type priv_max_size(container_detail::false_type, const Alloc &) BOOST_CONTAINER_NOEXCEPT
312       {  return size_type(-1);  }
313
314       static Alloc priv_select_on_container_copy_construction(container_detail::true_type, const Alloc &a)
315       {  return a.select_on_container_copy_construction();  }
316
317       static const Alloc &priv_select_on_container_copy_construction(container_detail::false_type, const Alloc &a) BOOST_CONTAINER_NOEXCEPT
318       {  return a;  }
319
320       #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
321          template<class T, class ...Args>
322          static void priv_construct(container_detail::false_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
323          {
324             const bool value = boost::container::container_detail::
325                   has_member_function_callable_with_construct
326                      < Alloc, T*, Args... >::value;
327             container_detail::bool_<value> flag;
328             priv_construct_dispatch2(flag, a, p, ::boost::forward<Args>(args)...);
329          }
330
331          template<class T, class ...Args>
332          static void priv_construct(container_detail::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
333          {
334             priv_construct_dispatch2(container_detail::false_type(), a, p, ::boost::forward<Args>(args)...);
335          }
336
337          template<class T, class ...Args>
338          static void priv_construct_dispatch2(container_detail::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
339          {  a.construct( p, ::boost::forward<Args>(args)...);  }
340
341          template<class T, class ...Args>
342          static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p, BOOST_FWD_REF(Args) ...args)
343          {  ::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...); }
344       #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
345          public:
346          #define BOOST_PP_LOCAL_MACRO(n)                                                              \
347          template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) >                                 \
348          static void construct(Alloc &a, T *p                                                         \
349                               BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _))            \
350          {                                                                                            \
351             container_detail::bool_                                                                   \
352                <container_detail::is_std_allocator<Alloc>::value> flag;                               \
353             allocator_traits::priv_construct(flag, a, p                                               \
354                BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));                       \
355          }                                                                                            \
356          //
357          #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
358          #include BOOST_PP_LOCAL_ITERATE()
359
360          private:
361          #define BOOST_PP_LOCAL_MACRO(n)                                                                    \
362          template<class T  BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) >                                      \
363          static void priv_construct(container_detail::false_type, Alloc &a, T *p                            \
364                         BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_))                         \
365          {                                                                                                  \
366             const bool value =                                                                              \
367                boost::container::container_detail::has_member_function_callable_with_construct              \
368                      < Alloc, T* BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_FWD_TYPE, _) >::value;        \
369             container_detail::bool_<value> flag;                                                            \
370             priv_construct_dispatch2(flag, a, p                                                             \
371                BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) );                            \
372          }                                                                                                  \
373                                                                                                             \
374          template<class T  BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) >                                      \
375          static void priv_construct(container_detail::true_type, Alloc &a, T *p                             \
376                         BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_))                         \
377          {                                                                                                  \
378             priv_construct_dispatch2(container_detail::false_type(), a, p                                   \
379                BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) );                            \
380          }                                                                                                  \
381                                                                                                             \
382          template<class T  BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) >                                      \
383          static void priv_construct_dispatch2(container_detail::true_type, Alloc &a, T *p                   \
384                         BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_))                         \
385          {  a.construct( p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) );  }             \
386                                                                                                             \
387          template<class T  BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) >                                      \
388          static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p                   \
389                         BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) )                       \
390          {  ::new((void*)p, boost_container_new_t()) T(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); }\
391          //
392          #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
393          #include BOOST_PP_LOCAL_ITERATE()
394       #endif   // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
395
396       template<class T>
397       static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p, ::boost::container::default_init_t)
398       {  ::new((void*)p) T; }
399    #endif   //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
400
401    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
402 };
403
404 }  //namespace container {
405 }  //namespace boost {
406
407 #include <boost/container/detail/config_end.hpp>
408
409 #endif // ! defined(BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP)