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