| |
| // Copyright 2005-2009 Daniel James. |
| // 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) |
| |
| // A couple of templates to make using allocators easier. |
| |
| #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 <boost/config.hpp> |
| |
| #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 <boost/detail/allocator_utilities.hpp> |
| #endif |
| |
| namespace boost { namespace unordered_detail { |
| |
| // rebind_wrap |
| // |
| // Rebind allocators. For some problematic libraries, use rebind_to |
| // from <boost/detail/allocator_utilities.hpp>. |
| |
| #if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES) |
| template <class Alloc, class T> |
| struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {}; |
| #else |
| template <class Alloc, class T> |
| struct rebind_wrap |
| { |
| typedef BOOST_DEDUCED_TYPENAME |
| Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other |
| type; |
| }; |
| #endif |
| |
| // allocator_array_constructor |
| // |
| // Allocate and construct an array in an exception safe manner, and |
| // clean up if an exception is thrown before the container takes charge |
| // of it. |
| |
| template <class Allocator> |
| struct allocator_array_constructor |
| { |
| typedef BOOST_DEDUCED_TYPENAME Allocator::pointer pointer; |
| |
| Allocator& alloc_; |
| pointer ptr_; |
| pointer constructed_; |
| std::size_t length_; |
| |
| allocator_array_constructor(Allocator& a) |
| : alloc_(a), ptr_(), constructed_(), length_(0) |
| { |
| constructed_ = pointer(); |
| ptr_ = pointer(); |
| } |
| |
| ~allocator_array_constructor() { |
| if (ptr_) { |
| for(pointer p = ptr_; p != constructed_; ++p) |
| alloc_.destroy(p); |
| |
| alloc_.deallocate(ptr_, length_); |
| } |
| } |
| |
| template <class V> |
| void construct(V const& v, std::size_t l) |
| { |
| BOOST_ASSERT(!ptr_); |
| length_ = l; |
| ptr_ = alloc_.allocate(length_); |
| pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_); |
| for(constructed_ = ptr_; constructed_ != end; ++constructed_) |
| alloc_.construct(constructed_, v); |
| } |
| |
| pointer get() const |
| { |
| return ptr_; |
| } |
| |
| pointer release() |
| { |
| pointer p(ptr_); |
| ptr_ = pointer(); |
| 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 |