williamr@2: /* Copyright 2003-2005 Joaquín M López Muñoz. williamr@2: * Distributed under the Boost Software License, Version 1.0. williamr@2: * (See accompanying file LICENSE_1_0.txt or copy at williamr@2: * http://www.boost.org/LICENSE_1_0.txt) williamr@2: * williamr@2: * See Boost website at http://www.boost.org/ williamr@2: */ williamr@2: williamr@2: #ifndef BOOST_DETAIL_ALLOCATOR_UTILITIES_HPP williamr@2: #define BOOST_DETAIL_ALLOCATOR_UTILITIES_HPP williamr@2: williamr@2: #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ williamr@2: #include <boost/detail/workaround.hpp> williamr@2: #include <boost/mpl/aux_/msvc_never_true.hpp> williamr@2: #include <boost/mpl/eval_if.hpp> williamr@2: #include <boost/type_traits/is_same.hpp> williamr@2: #include <cstddef> williamr@2: #include <memory> williamr@2: #include <new> williamr@2: williamr@2: namespace boost{ williamr@2: williamr@2: namespace detail{ williamr@2: williamr@2: /* Allocator adaption layer. Some stdlibs provide allocators without rebind williamr@2: * and template ctors. These facilities are simulated with the external williamr@2: * template class rebind_to and the aid of partial_std_allocator_wrapper. williamr@2: */ williamr@2: williamr@2: namespace allocator{ williamr@2: williamr@2: /* partial_std_allocator_wrapper inherits the functionality of a std williamr@2: * allocator while providing a templatized ctor. williamr@2: */ williamr@2: williamr@2: template<typename Type> williamr@2: class partial_std_allocator_wrapper:public std::allocator<Type> williamr@2: { williamr@2: public: williamr@2: partial_std_allocator_wrapper(){}; williamr@2: williamr@2: template<typename Other> williamr@2: partial_std_allocator_wrapper(const partial_std_allocator_wrapper<Other>&){} williamr@2: williamr@2: partial_std_allocator_wrapper(const std::allocator<Type>& x): williamr@2: std::allocator<Type>(x) williamr@2: { williamr@2: }; williamr@2: williamr@2: #if defined(BOOST_DINKUMWARE_STDLIB) williamr@2: /* Dinkumware guys didn't provide a means to call allocate() without williamr@2: * supplying a hint, in disagreement with the standard. williamr@2: */ williamr@2: williamr@2: Type* allocate(std::size_t n,const void* hint=0) williamr@2: { williamr@2: std::allocator<Type>& a=*this; williamr@2: return a.allocate(n,hint); williamr@2: } williamr@2: #endif williamr@2: williamr@2: }; williamr@2: williamr@2: /* Detects whether a given allocator belongs to a defective stdlib not williamr@2: * having the required member templates. williamr@2: * Note that it does not suffice to check the Boost.Config stdlib williamr@2: * macros, as the user might have passed a custom, compliant allocator. williamr@2: * The checks also considers partial_std_allocator_wrapper to be williamr@2: * a standard defective allocator. williamr@2: */ williamr@2: williamr@2: #if defined(BOOST_NO_STD_ALLOCATOR)&&\ williamr@2: (defined(BOOST_HAS_PARTIAL_STD_ALLOCATOR)||defined(BOOST_DINKUMWARE_STDLIB)) williamr@2: williamr@2: template<typename Allocator> williamr@2: struct is_partial_std_allocator williamr@2: { williamr@2: BOOST_STATIC_CONSTANT(bool, williamr@2: value= williamr@2: (is_same< williamr@2: std::allocator<BOOST_DEDUCED_TYPENAME Allocator::value_type>, williamr@2: Allocator williamr@2: >::value)|| williamr@2: (is_same< williamr@2: partial_std_allocator_wrapper< williamr@2: BOOST_DEDUCED_TYPENAME Allocator::value_type>, williamr@2: Allocator williamr@2: >::value)); williamr@2: }; williamr@2: williamr@2: #else williamr@2: williamr@2: template<typename Allocator> williamr@2: struct is_partial_std_allocator williamr@2: { williamr@2: BOOST_STATIC_CONSTANT(bool,value=false); williamr@2: }; williamr@2: williamr@2: #endif williamr@2: williamr@2: /* rebind operations for defective std allocators */ williamr@2: williamr@2: template<typename Allocator,typename Type> williamr@2: struct partial_std_allocator_rebind_to williamr@2: { williamr@2: typedef partial_std_allocator_wrapper<Type> type; williamr@2: }; williamr@2: williamr@2: /* rebind operation in all other cases */ williamr@2: williamr@2: #if BOOST_WORKAROUND(BOOST_MSVC,<1300) williamr@2: /* Workaround for a problem in MSVC with dependent template typedefs williamr@2: * when doing rebinding of allocators. williamr@2: * Modeled after <boost/mpl/aux_/msvc_dtw.hpp> (thanks, Aleksey!) williamr@2: */ williamr@2: williamr@2: template<typename Allocator> williamr@2: struct rebinder williamr@2: { williamr@2: template<bool> struct fake_allocator:Allocator{}; williamr@2: template<> struct fake_allocator<true> williamr@2: { williamr@2: template<typename Type> struct rebind{}; williamr@2: }; williamr@2: williamr@2: template<typename Type> williamr@2: struct result: williamr@2: fake_allocator<mpl::aux::msvc_never_true<Allocator>::value>:: williamr@2: template rebind<Type> williamr@2: { williamr@2: }; williamr@2: }; williamr@2: #else williamr@2: template<typename Allocator> williamr@2: struct rebinder williamr@2: { williamr@2: template<typename Type> williamr@2: struct result williamr@2: { williamr@2: typedef typename Allocator::BOOST_NESTED_TEMPLATE williamr@2: rebind<Type>::other other; williamr@2: }; williamr@2: }; williamr@2: #endif williamr@2: williamr@2: template<typename Allocator,typename Type> williamr@2: struct compliant_allocator_rebind_to williamr@2: { williamr@2: typedef typename rebinder<Allocator>:: williamr@2: BOOST_NESTED_TEMPLATE result<Type>::other type; williamr@2: }; williamr@2: williamr@2: /* rebind front-end */ williamr@2: williamr@2: template<typename Allocator,typename Type> williamr@2: struct rebind_to: williamr@2: mpl::eval_if_c< williamr@2: is_partial_std_allocator<Allocator>::value, williamr@2: partial_std_allocator_rebind_to<Allocator,Type>, williamr@2: compliant_allocator_rebind_to<Allocator,Type> williamr@2: > williamr@2: { williamr@2: }; williamr@2: williamr@2: /* allocator-independent versions of construct and destroy */ williamr@2: williamr@2: template<typename Type> williamr@2: void construct(void* p,const Type& t) williamr@2: { williamr@2: new (p) Type(t); williamr@2: } williamr@2: williamr@2: template<typename Type> williamr@2: void destroy(const Type* p) williamr@2: { williamr@2: p->~Type(); williamr@2: } williamr@2: williamr@2: } /* namespace boost::detail::allocator */ williamr@2: williamr@2: } /* namespace boost::detail */ williamr@2: williamr@2: } /* namespace boost */ williamr@2: williamr@2: #endif