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