// Copyright 2006-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) #if !defined(BOOST_UNORDERED_TEST_OBJECTS_HEADER) #define BOOST_UNORDERED_TEST_OBJECTS_HEADER #include #include #include #include "../helpers/fwd.hpp" #include "../helpers/count.hpp" #include "../helpers/memory.hpp" namespace test { // Note that the default hash function will work for any equal_to (but not // very well). class object; class implicitly_convertible; class hash; class less; class equal_to; template class allocator1; template class allocator2; object generate(object const*); implicitly_convertible generate(implicitly_convertible const*); inline void ignore_variable(void const*) {} class object : private counted_object { friend class hash; friend class equal_to; friend class less; int tag1_, tag2_; public: explicit object(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {} ~object() { tag1_ = -1; tag2_ = -1; } friend bool operator==(object const& x1, object const& x2) { return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_; } friend bool operator!=(object const& x1, object const& x2) { return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_; } friend bool operator<(object const& x1, object const& x2) { return x1.tag1_ < x2.tag1_ || (x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_); } friend object generate(object const*) { int* x = 0; return object(generate(x), generate(x)); } friend std::ostream& operator<<(std::ostream& out, object const& o) { return out<<"("< class allocator1 { public: int tag_; typedef T value_type; template struct rebind { typedef allocator1 other; }; explicit allocator1(int t = 0) : tag_(t) { detail::tracker.allocator_ref(); } template allocator1(allocator1 const& x) : tag_(x.tag_) { detail::tracker.allocator_ref(); } allocator1(allocator1 const& x) : tag_(x.tag_) { detail::tracker.allocator_ref(); } ~allocator1() { detail::tracker.allocator_unref(); } T* allocate(std::size_t n) { T* ptr(static_cast(::operator new(n * sizeof(T)))); detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_); return ptr; } T* allocate(std::size_t n, void const* u) { T* ptr(static_cast(::operator new(n * sizeof(T)))); detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_); return ptr; } void deallocate(T* p, std::size_t n) { detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_); ::operator delete((void*) p); } void construct(T* p, T const& t) { // Don't count constructions here as it isn't always called. //detail::tracker.track_construct((void*) p, sizeof(T), tag_); new(p) T(t); } void destroy(T* p) { //detail::tracker.track_destroy((void*) p, sizeof(T), tag_); p->~T(); // Work around MSVC buggy unused parameter warning. ignore_variable(&p); } bool operator==(allocator1 const& x) const { return tag_ == x.tag_; } bool operator!=(allocator1 const& x) const { return tag_ != x.tag_; } enum { is_select_on_copy = false, is_propagate_on_swap = false, is_propagate_on_assign = false, is_propagate_on_move = false }; }; template class allocator2 { # ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS public: # else template friend class allocator2; # endif int tag_; public: typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef T* pointer; typedef T const* const_pointer; typedef T& reference; typedef T const& const_reference; typedef T value_type; template struct rebind { typedef allocator2 other; }; explicit allocator2(int t = 0) : tag_(t) { detail::tracker.allocator_ref(); } template allocator2(allocator2 const& x) : tag_(x.tag_) { detail::tracker.allocator_ref(); } allocator2(allocator2 const& x) : tag_(x.tag_) { detail::tracker.allocator_ref(); } ~allocator2() { detail::tracker.allocator_unref(); } pointer address(reference r) { return pointer(&r); } const_pointer address(const_reference r) { return const_pointer(&r); } 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 allocate(size_type n, void const* u) { pointer ptr(static_cast(::operator new(n * sizeof(T)))); detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_); return ptr; } void deallocate(pointer p, size_type n) { detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_); ::operator delete((void*) p); } void construct(T* p, T const& t) { detail::tracker.track_construct((void*) p, sizeof(T), tag_); new(p) T(t); } #if !defined(BOOST_NO_VARIADIC_TEMPLATES) template void construct(T* p, BOOST_FWD_REF(Args)... args) { detail::tracker.track_construct((void*) p, sizeof(T), tag_); new(p) T(boost::forward(args)...); } #endif void destroy(T* p) { detail::tracker.track_destroy((void*) p, sizeof(T), tag_); p->~T(); } size_type max_size() const { return (std::numeric_limits::max)(); } bool operator==(allocator2 const& x) const { return tag_ == x.tag_; } bool operator!=(allocator2 const& x) const { return tag_ != x.tag_; } enum { is_select_on_copy = false, is_propagate_on_swap = false, is_propagate_on_assign = false, is_propagate_on_move = false }; }; template bool equivalent_impl(allocator1 const& x, allocator1 const& y, test::derived_type) { return x == y; } template bool equivalent_impl(allocator2 const& x, allocator2 const& y, test::derived_type) { return x == y; } } #endif