diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 4198a8f7..70a46572 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -429,7 +429,7 @@ namespace boost { namespace unordered { namespace detail { a.construct(); (constructor.get() + - static_cast(bucket_count_))->next_ = + static_cast(new_count))->next_ = a.release(); } diff --git a/test/objects/test.hpp b/test/objects/test.hpp index ce9c698b..8e2b3aa6 100644 --- a/test/objects/test.hpp +++ b/test/objects/test.hpp @@ -186,9 +186,8 @@ namespace test } }; - // allocator1 and allocator2 are pretty similar. // allocator1 only has the old fashioned 'construct' method and has - // a few less typedefs + // a few less typedefs. allocator2 uses a custom pointer class. template class allocator1 @@ -273,6 +272,127 @@ namespace test }; }; + template class ptr; + template class const_ptr; + + struct void_ptr + { +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template + friend class ptr; + private: +#endif + + void* ptr_; + + public: + void_ptr() : ptr_(0) {} + + template + explicit void_ptr(ptr const& x) : ptr_(x.ptr_) {} + + // I'm not using the safe bool idiom because the containers should be + // able to cope with bool conversions. + operator bool() const { return !!ptr_; } + + bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; } + bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; } + }; + + class void_const_ptr + { +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template + friend class const_ptr; + private: +#endif + + void* ptr_; + + public: + void_const_ptr() : ptr_(0) {} + + template + explicit void_const_ptr(const_ptr const& x) : ptr_(x.ptr_) {} + + // I'm not using the safe bool idiom because the containers should be + // able to cope with bool conversions. + operator bool() const { return !!ptr_; } + + bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; } + bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; } + }; + + template + class ptr + { + friend class allocator2; + friend class const_ptr; + friend struct void_ptr; + + T* ptr_; + + ptr(T* x) : ptr_(x) {} + public: + ptr() : ptr_(0) {} + explicit ptr(void_ptr const& x) : ptr_((T*) x.ptr_) {} + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + ptr& operator++() { ++ptr_; return *this; } + ptr operator++(int) { ptr tmp(*this); ++ptr_; return tmp; } + ptr operator+(std::ptrdiff_t s) const { return ptr(ptr_ + s); } + friend ptr operator+(std::ptrdiff_t s, ptr p) + { return ptr(s + p.ptr_); } + T& operator[](std::ptrdiff_t s) const { return ptr_[s]; } + bool operator!() const { return !ptr_; } + + // I'm not using the safe bool idiom because the containers should be + // able to cope with bool conversions. + operator bool() const { return !!ptr_; } + + bool operator==(ptr const& x) const { return ptr_ == x.ptr_; } + bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; } + bool operator<(ptr const& x) const { return ptr_ < x.ptr_; } + bool operator>(ptr const& x) const { return ptr_ > x.ptr_; } + bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; } + bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; } + }; + + template + class const_ptr + { + friend class allocator2; + friend struct const_void_ptr; + + T const* ptr_; + + const_ptr(T const* ptr) : ptr_(ptr) {} + public: + const_ptr() : ptr_(0) {} + const_ptr(ptr const& x) : ptr_(x.ptr_) {} + explicit const_ptr(void_const_ptr const& x) : ptr_((T const*) x.ptr_) {} + + T const& operator*() const { return *ptr_; } + T const* operator->() const { return ptr_; } + const_ptr& operator++() { ++ptr_; return *this; } + const_ptr operator++(int) { const_ptr tmp(*this); ++ptr_; return tmp; } + const_ptr operator+(std::ptrdiff_t s) const + { return const_ptr(ptr_ + s); } + friend const_ptr operator+(std::ptrdiff_t s, const_ptr p) + { return ptr(s + p.ptr_); } + T const& operator[](int s) const { return ptr_[s]; } + bool operator!() const { return !ptr_; } + operator bool() const { return !!ptr_; } + + bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; } + bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; } + bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; } + bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; } + bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; } + bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; } + }; + template class allocator2 { @@ -285,8 +405,10 @@ namespace test public: typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; - typedef T* pointer; - typedef T const* const_pointer; + typedef void_ptr void_pointer; + typedef void_const_ptr const_void_pointer; + typedef ptr pointer; + typedef const_ptr const_pointer; typedef T& reference; typedef T const& const_reference; typedef T value_type; @@ -326,9 +448,9 @@ namespace test } pointer allocate(size_type n) { - pointer ptr(static_cast(::operator new(n * sizeof(T)))); - detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_); - return ptr; + pointer p(static_cast(::operator new(n * sizeof(T)))); + detail::tracker.track_allocate((void*) p.ptr_, n, sizeof(T), tag_); + return p; } pointer allocate(size_type n, void const* u) @@ -340,8 +462,8 @@ namespace test void deallocate(pointer p, size_type n) { - detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_); - ::operator delete((void*) p); + detail::tracker.track_deallocate((void*) p.ptr_, n, sizeof(T), tag_); + ::operator delete((void*) p.ptr_); } void construct(T* p, T const& t) {