// (C) Copyright Daniel James 2005. // Use, modification and distribution are subject to 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) #ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED #define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif #include #if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \ && !defined(__BORLANDC__) # define BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES #endif #if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES) # include #endif #include namespace boost { namespace unordered_detail { #if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES) template struct rebind_wrap : ::boost::detail::allocator::rebind_to {}; #else template struct rebind_wrap { typedef BOOST_DEDUCED_TYPENAME Alloc::BOOST_NESTED_TEMPLATE rebind::other type; }; #endif #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) template inline void reset(T& x) { x = T(); } #else template inline void reset_impl(T& x, ...) { x = T(); } template inline void reset_impl(T*& x, int) { x = 0; } template inline void reset(T& x) { reset_impl(x); } #endif // Work around for Microsoft's ETI bug. template struct allocator_value_type { typedef typename Allocator::value_type type; }; template struct allocator_pointer { typedef typename Allocator::pointer type; }; template struct allocator_const_pointer { typedef typename Allocator::const_pointer type; }; template struct allocator_reference { typedef typename Allocator::reference type; }; template struct allocator_const_reference { typedef typename Allocator::const_reference type; }; #if defined(BOOST_MPL_CFG_MSVC_ETI_BUG) template <> struct allocator_value_type { typedef int type; }; template <> struct allocator_pointer { typedef int type; }; template <> struct allocator_const_pointer { typedef int type; }; template <> struct allocator_reference { typedef int type; }; template <> struct allocator_const_reference { typedef int type; }; #endif template struct allocator_constructor { typedef typename allocator_pointer::type pointer; Allocator& alloc_; pointer ptr_; allocator_constructor(Allocator& a) : alloc_(a), ptr_() { #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) unordered_detail::reset(ptr_); #endif } ~allocator_constructor() { if (ptr_) alloc_.deallocate(ptr_, 1); } template pointer construct(V const& v) { BOOST_ASSERT(!ptr_); pointer p = alloc_.allocate(1); ptr_ = p; alloc_.construct(p, v); reset(ptr_); return p; } // no throw pointer release() { pointer p = ptr_; reset(ptr_); return p; } }; template struct allocator_array_constructor { typedef typename allocator_pointer::type pointer; Allocator& alloc_; pointer ptr_; pointer constructed_; std::size_t length_; allocator_array_constructor(Allocator& a) : alloc_(a), ptr_(), constructed_(), length_(0) { #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) unordered_detail::reset(constructed_); unordered_detail::reset(ptr_); #endif } ~allocator_array_constructor() { if (ptr_) { for(pointer p = ptr_; p != constructed_; ++p) alloc_.destroy(p); alloc_.deallocate(ptr_, length_); } } template void construct(V const& v, std::size_t l) { BOOST_ASSERT(!ptr_); length_ = l; ptr_ = alloc_.allocate(length_); pointer end = ptr_ + length_; for(constructed_ = ptr_; constructed_ != end; ++constructed_) alloc_.construct(constructed_, v); } pointer get() const { return ptr_; } pointer release() { pointer p(ptr_); reset(ptr_); return p; } private: allocator_array_constructor(allocator_array_constructor const&); allocator_array_constructor& operator=(allocator_array_constructor const&); }; } } #if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES) # undef BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES #endif #endif