////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Pablo Halpern 2009. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // ////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP #define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP #if (defined _MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif #include #include #include #include #include #include #include #include #include //numeric_limits<>::max() #include //placement new #include //std::allocator #include ///@cond namespace boost { namespace container { namespace container_detail { //workaround needed for C++03 compilers with no construct() //supporting rvalue references template struct is_std_allocator { static const bool value = false; }; template struct is_std_allocator< std::allocator > { static const bool value = true; }; } //namespace container_detail { ///@endcond //! The class template allocator_traits supplies a uniform interface to all allocator types. //! This class is a C++03-compatible implementation of std::allocator_traits template struct allocator_traits { //allocator_type typedef Alloc allocator_type; //value_type typedef typename Alloc::value_type value_type; #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Alloc::pointer if such a type exists; otherwise, value_type* //! typedef unspecified pointer; //! Alloc::const_pointer if such a type exists ; otherwise, pointer_traits::rebind::rebind. //! typedef see_documentation void_pointer; //! Alloc::const_void_pointer if such a type exists ; otherwis e, pointer_traits::rebind::difference_type. //! typedef see_documentation difference_type; //! Alloc::size_type if such a type exists ; otherwise, make_unsigned::type //! typedef see_documentation size_type; //! Alloc::propagate_on_container_copy_assignment if such a type exists, otherwise an integral_constant //! type with internal constant static member `value` == false. typedef see_documentation propagate_on_container_copy_assignment; //! Alloc::propagate_on_container_move_assignment if such a type exists, otherwise an integral_constant //! type with internal constant static member `value` == false. typedef see_documentation propagate_on_container_move_assignment; //! Alloc::propagate_on_container_swap if such a type exists, otherwise an integral_constant //! type with internal constant static member `value` == false. typedef see_documentation propagate_on_container_swap; //! Defines an allocator: Alloc::rebind::other if such a type exists; otherwise, Alloc //! if Alloc is a class template instantiation of the form Alloc, where Args is zero or //! more type arguments ; otherwise, the instantiation of rebind_alloc is ill-formed. //! //! In C++03 compilers `rebind_alloc` is a struct derived from an allocator //! deduced by previously detailed rules. template using rebind_alloc = see_documentation; //! In C++03 compilers `rebind_traits` is a struct derived from //! `allocator_traits`, where `OtherAlloc` is //! the allocator deduced by rules explained in `rebind_alloc`. template using rebind_traits = allocator_traits >; //! Non-standard extension: Portable allocator rebind for C++03 and C++11 compilers. //! `type` is an allocator related to Alloc deduced deduced by rules explained in `rebind_alloc`. template struct portable_rebind_alloc { typedef see_documentation type; }; #else //pointer typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, pointer, value_type*) pointer; //const_pointer typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc, const_pointer, typename boost::intrusive::pointer_traits::template rebind_pointer) const_pointer; //reference typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, reference, typename container_detail::unvoid::type&) reference; //const_reference typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, const_reference, const typename container_detail::unvoid::type&) const_reference; //void_pointer typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc, void_pointer, typename boost::intrusive::pointer_traits::template rebind_pointer) void_pointer; //const_void_pointer typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc, const_void_pointer, typename boost::intrusive::pointer_traits::template rebind_pointer) const_void_pointer; //difference_type typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, difference_type, std::ptrdiff_t) difference_type; //size_type typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, size_type, std::size_t) size_type; //propagate_on_container_copy_assignment typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, propagate_on_container_copy_assignment, boost::false_type) propagate_on_container_copy_assignment; //propagate_on_container_move_assignment typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, propagate_on_container_move_assignment, boost::false_type) propagate_on_container_move_assignment; //propagate_on_container_swap typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, propagate_on_container_swap, boost::false_type) propagate_on_container_swap; #if !defined(BOOST_NO_TEMPLATE_ALIASES) //C++11 template using rebind_alloc = typename boost::intrusive::detail::type_rebinder::type; template using rebind_traits = allocator_traits< rebind_alloc >; #else // #if !defined(BOOST_NO_TEMPLATE_ALIASES) //Some workaround for C++03 or C++11 compilers with no template aliases template struct rebind_alloc : boost::intrusive::detail::type_rebinder::type { typedef typename boost::intrusive::detail::type_rebinder::type Base; #if !defined(BOOST_NO_VARIADIC_TEMPLATES) template rebind_alloc(BOOST_FWD_REF(Args)... args) : Base(boost::forward(args)...) {} #else // #if !defined(BOOST_NO_VARIADIC_TEMPLATES) #define BOOST_PP_LOCAL_MACRO(n) \ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ rebind_alloc(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ : Base(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)) \ {} \ // #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() #endif // #if !defined(BOOST_NO_VARIADIC_TEMPLATES) }; template struct rebind_traits : allocator_traits::type> {}; #endif // #if !defined(BOOST_NO_TEMPLATE_ALIASES) template struct portable_rebind_alloc { typedef typename boost::intrusive::detail::type_rebinder::type type; }; #endif //BOOST_CONTAINER_DOXYGEN_INVOKED //! Returns: `a.allocate(n)` //! static pointer allocate(Alloc &a, size_type n) { return a.allocate(n); } //! Returns: `a.deallocate(p, n)` //! //! Throws: Nothing static void deallocate(Alloc &a, pointer p, size_type n) { return a.deallocate(p, n); } //! Effects: calls `a.allocate(n, p)` if that call is well-formed; //! otherwise, invokes `a.allocate(n)` static pointer allocate(Alloc &a, size_type n, const_void_pointer p) { const bool value = boost::container::container_detail:: has_member_function_callable_with_allocate ::value; ::boost::integral_constant flag; return allocator_traits::priv_allocate(flag, a, n, p); } //! Effects: calls `a.destroy(p)` if that call is well-formed; //! otherwise, invokes `p->~T()`. template static void destroy(Alloc &a, T*p) { typedef T* destroy_pointer; const bool value = boost::container::container_detail:: has_member_function_callable_with_destroy ::value; ::boost::integral_constant flag; allocator_traits::priv_destroy(flag, a, p); } //! Returns: `a.max_size()` if that expression is well-formed; otherwise, //! `numeric_limits::max()`. static size_type max_size(const Alloc &a) { const bool value = boost::container::container_detail:: has_member_function_callable_with_max_size ::value; ::boost::integral_constant flag; return allocator_traits::priv_max_size(flag, a); } //! Returns: `a.select_on_container_copy_construction()` if that expression is well-formed; //! otherwise, a. static Alloc select_on_container_copy_construction(const Alloc &a) { const bool value = boost::container::container_detail:: has_member_function_callable_with_select_on_container_copy_construction ::value; ::boost::integral_constant flag; return allocator_traits::priv_select_on_container_copy_construction(flag, a); } #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Effects: calls `a.construct(p, std::forward(args)...)` if that call is well-formed; //! otherwise, invokes `::new (static_cast(p)) T(std::forward(args)...)` template static void construct(Alloc & a, T* p, BOOST_FWD_REF(Args)... args) { ::boost::integral_constant::value> flag; allocator_traits::priv_construct(flag, a, p, ::boost::forward(args)...); } #endif ///@cond #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) private: static pointer priv_allocate(boost::true_type, Alloc &a, size_type n, const_void_pointer p) { return a.allocate(n, p); } static pointer priv_allocate(boost::false_type, Alloc &a, size_type n, const_void_pointer) { return allocator_traits::allocate(a, n); } template static void priv_destroy(boost::true_type, Alloc &a, T* p) { a.destroy(p); } template static void priv_destroy(boost::false_type, Alloc &, T* p) { p->~T(); (void)p; } static size_type priv_max_size(boost::true_type, const Alloc &a) { return a.max_size(); } static size_type priv_max_size(boost::false_type, const Alloc &) { return (std::numeric_limits::max)(); } static Alloc priv_select_on_container_copy_construction(boost::true_type, const Alloc &a) { return a.select_on_container_copy_construction(); } static Alloc priv_select_on_container_copy_construction(boost::false_type, const Alloc &a) { return a; } #if !defined(BOOST_NO_VARIADIC_TEMPLATES) template static void priv_construct(boost::false_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args) { const bool value = boost::container::container_detail:: has_member_function_callable_with_construct < Alloc, T*, Args... >::value; ::boost::integral_constant flag; priv_construct_dispatch2(flag, a, p, ::boost::forward(args)...); } template static void priv_construct(boost::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args) { priv_construct_dispatch2(boost::false_type(), a, p, ::boost::forward(args)...); } template static void priv_construct_dispatch2(boost::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args) { a.construct( p, ::boost::forward(args)...); } template static void priv_construct_dispatch2(boost::false_type, Alloc &, T *p, BOOST_FWD_REF(Args) ...args) { ::new((void*)p) T(::boost::forward(args)...); } #else // #if !defined(BOOST_NO_VARIADIC_TEMPLATES) public: #define BOOST_PP_LOCAL_MACRO(n) \ template \ static void construct(Alloc &a, T *p \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ { \ ::boost::integral_constant::value> flag; \ allocator_traits::priv_construct(flag, a, p \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ } \ // #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() private: #define BOOST_PP_LOCAL_MACRO(n) \ template \ static void priv_construct(boost::false_type, Alloc &a, T *p \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \ { \ const bool value = \ boost::container::container_detail::has_member_function_callable_with_construct \ < Alloc, T* BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_FWD_TYPE, _) >::value; \ ::boost::integral_constant flag; \ priv_construct_dispatch2(flag, a, p \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ } \ \ template \ static void priv_construct(boost::true_type, Alloc &a, T *p \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \ { \ priv_construct_dispatch2(boost::false_type(), a, p \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ } \ \ template \ static void priv_construct_dispatch2(boost::true_type, Alloc &a, T *p \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \ { a.construct( p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); } \ \ template \ static void priv_construct_dispatch2(boost::false_type, Alloc &, T *p \ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \ { ::new((void*)p) T(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ // #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() #endif // #if !defined(BOOST_NO_VARIADIC_TEMPLATES) #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) ///@endcond }; } //namespace container { } //namespace boost { #include #endif // ! defined(BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP)