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
							 |