Chris@101: /* Copyright 2003-2013 Joaquin M Lopez Munoz. Chris@16: * Distributed under the Boost Software License, Version 1.0. Chris@16: * (See accompanying file LICENSE_1_0.txt or copy at Chris@16: * http://www.boost.org/LICENSE_1_0.txt) Chris@16: * Chris@16: * See Boost website at http://www.boost.org/ Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_DETAIL_ALLOCATOR_UTILITIES_HPP Chris@16: #define BOOST_DETAIL_ALLOCATOR_UTILITIES_HPP Chris@16: Chris@16: #include /* keep it first to prevent nasty warns in MSVC */ Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost{ Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: /* Allocator adaption layer. Some stdlibs provide allocators without rebind Chris@16: * and template ctors. These facilities are simulated with the external Chris@16: * template class rebind_to and the aid of partial_std_allocator_wrapper. Chris@16: */ Chris@16: Chris@16: namespace allocator{ Chris@16: Chris@16: /* partial_std_allocator_wrapper inherits the functionality of a std Chris@16: * allocator while providing a templatized ctor and other bits missing Chris@16: * in some stdlib implementation or another. Chris@16: */ Chris@16: Chris@16: template Chris@16: class partial_std_allocator_wrapper:public std::allocator Chris@16: { Chris@16: public: Chris@16: /* Oddly enough, STLport does not define std::allocator::value_type Chris@16: * when configured to work without partial template specialization. Chris@16: * No harm in supplying the definition here unconditionally. Chris@16: */ Chris@16: Chris@16: typedef Type value_type; Chris@16: Chris@16: partial_std_allocator_wrapper(){}; Chris@16: Chris@16: template Chris@16: partial_std_allocator_wrapper(const partial_std_allocator_wrapper&){} Chris@16: Chris@16: partial_std_allocator_wrapper(const std::allocator& x): Chris@16: std::allocator(x) Chris@16: { Chris@16: }; Chris@16: Chris@16: #if defined(BOOST_DINKUMWARE_STDLIB) Chris@16: /* Dinkumware guys didn't provide a means to call allocate() without Chris@16: * supplying a hint, in disagreement with the standard. Chris@16: */ Chris@16: Chris@16: Type* allocate(std::size_t n,const void* hint=0) Chris@16: { Chris@16: std::allocator& a=*this; Chris@16: return a.allocate(n,hint); Chris@16: } Chris@16: #endif Chris@16: Chris@16: }; Chris@16: Chris@16: /* Detects whether a given allocator belongs to a defective stdlib not Chris@16: * having the required member templates. Chris@16: * Note that it does not suffice to check the Boost.Config stdlib Chris@16: * macros, as the user might have passed a custom, compliant allocator. Chris@16: * The checks also considers partial_std_allocator_wrapper to be Chris@16: * a standard defective allocator. Chris@16: */ Chris@16: Chris@16: #if defined(BOOST_NO_STD_ALLOCATOR)&&\ Chris@16: (defined(BOOST_HAS_PARTIAL_STD_ALLOCATOR)||defined(BOOST_DINKUMWARE_STDLIB)) Chris@16: Chris@16: template Chris@16: struct is_partial_std_allocator Chris@16: { Chris@16: BOOST_STATIC_CONSTANT(bool, Chris@16: value= Chris@16: (is_same< Chris@16: std::allocator, Chris@16: Allocator Chris@16: >::value)|| Chris@16: (is_same< Chris@16: partial_std_allocator_wrapper< Chris@16: BOOST_DEDUCED_TYPENAME Allocator::value_type>, Chris@16: Allocator Chris@16: >::value)); Chris@16: }; Chris@16: Chris@16: #else Chris@16: Chris@16: template Chris@16: struct is_partial_std_allocator Chris@16: { Chris@16: BOOST_STATIC_CONSTANT(bool,value=false); Chris@16: }; Chris@16: Chris@16: #endif Chris@16: Chris@16: /* rebind operations for defective std allocators */ Chris@16: Chris@16: template Chris@16: struct partial_std_allocator_rebind_to Chris@16: { Chris@16: typedef partial_std_allocator_wrapper type; Chris@16: }; Chris@16: Chris@16: /* rebind operation in all other cases */ Chris@16: Chris@16: template Chris@16: struct rebinder Chris@16: { Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename Allocator::BOOST_NESTED_TEMPLATE Chris@16: rebind::other other; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct compliant_allocator_rebind_to Chris@16: { Chris@16: typedef typename rebinder:: Chris@16: BOOST_NESTED_TEMPLATE result::other type; Chris@16: }; Chris@16: Chris@16: /* rebind front-end */ Chris@16: Chris@16: template Chris@16: struct rebind_to: Chris@16: mpl::eval_if_c< Chris@16: is_partial_std_allocator::value, Chris@16: partial_std_allocator_rebind_to, Chris@16: compliant_allocator_rebind_to Chris@16: > Chris@16: { Chris@16: }; Chris@16: Chris@16: /* allocator-independent versions of construct and destroy */ Chris@16: Chris@16: template Chris@16: void construct(void* p,const Type& t) Chris@16: { Chris@16: new (p) Type(t); Chris@16: } Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500)) Chris@16: /* MSVC++ issues spurious warnings about unreferencend formal parameters Chris@16: * in destroy when Type is a class with trivial dtor. Chris@16: */ Chris@16: Chris@16: #pragma warning(push) Chris@16: #pragma warning(disable:4100) Chris@16: #endif Chris@16: Chris@16: template Chris@16: void destroy(const Type* p) Chris@16: { Chris@16: Chris@16: #if BOOST_WORKAROUND(__SUNPRO_CC,BOOST_TESTED_AT(0x590)) Chris@16: const_cast(p)->~Type(); Chris@16: #else Chris@16: p->~Type(); Chris@16: #endif Chris@16: Chris@16: } Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500)) Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: } /* namespace boost::detail::allocator */ Chris@16: Chris@16: } /* namespace boost::detail */ Chris@16: Chris@16: } /* namespace boost */ Chris@16: Chris@16: #endif