1 #ifndef TEST_ALLOCATOR_H 2 #define TEST_ALLOCATOR_H 3 4 #include <cstddef> 5 #include <type_traits> 6 #include <cstdlib> 7 #include <new> 8 #include <climits> 9 10 class test_alloc_base 11 { 12 protected: 13 static int count; 14 public: 15 static int throw_after; 16 }; 17 18 int test_alloc_base::count = 0; 19 int test_alloc_base::throw_after = INT_MAX; 20 21 template <class T> 22 class test_allocator 23 : public test_alloc_base 24 { 25 int data_; 26 27 template <class U> friend class test_allocator; 28 public: 29 30 typedef unsigned size_type; 31 typedef int difference_type; 32 typedef T value_type; 33 typedef value_type* pointer; 34 typedef const value_type* const_pointer; 35 typedef typename std::add_lvalue_reference<value_type>::type reference; 36 typedef typename std::add_lvalue_reference<const value_type>::type const_reference; 37 38 template <class U> struct rebind {typedef test_allocator<U> other;}; 39 throw()40 test_allocator() throw() : data_(-1) {} test_allocator(int i)41 explicit test_allocator(int i) throw() : data_(i) {} throw()42 test_allocator(const test_allocator& a) throw() 43 : data_(a.data_) {} test_allocator(const test_allocator<U> & a)44 template <class U> test_allocator(const test_allocator<U>& a) throw() 45 : data_(a.data_) {} throw()46 ~test_allocator() throw() {data_ = 0;} address(reference x)47 pointer address(reference x) const {return &x;} address(const_reference x)48 const_pointer address(const_reference x) const {return &x;} 49 pointer allocate(size_type n, const void* = 0) 50 { 51 if (count >= throw_after) { 52 #ifndef _LIBCPP_NO_EXCEPTIONS 53 throw std::bad_alloc(); 54 #else 55 std::terminate(); 56 #endif 57 } 58 ++count; 59 return (pointer)std::malloc(n * sizeof(T)); 60 } deallocate(pointer p,size_type n)61 void deallocate(pointer p, size_type n) 62 {std::free(p);} max_size()63 size_type max_size() const throw() 64 {return UINT_MAX / sizeof(T);} construct(pointer p,const T & val)65 void construct(pointer p, const T& val) 66 {::new(p) T(val);} 67 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES construct(pointer p,T && val)68 void construct(pointer p, T&& val) 69 {::new(p) T(std::move(val));} 70 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES destroy(pointer p)71 void destroy(pointer p) {p->~T();} 72 73 friend bool operator==(const test_allocator& x, const test_allocator& y) 74 {return x.data_ == y.data_;} 75 friend bool operator!=(const test_allocator& x, const test_allocator& y) 76 {return !(x == y);} 77 }; 78 79 template <class T> 80 class other_allocator 81 { 82 int data_; 83 84 template <class U> friend class other_allocator; 85 86 public: 87 typedef T value_type; 88 other_allocator()89 other_allocator() : data_(-1) {} other_allocator(int i)90 explicit other_allocator(int i) : data_(i) {} other_allocator(const other_allocator<U> & a)91 template <class U> other_allocator(const other_allocator<U>& a) 92 : data_(a.data_) {} allocate(std::size_t n)93 T* allocate(std::size_t n) 94 {return (T*)std::malloc(n * sizeof(T));} deallocate(T * p,std::size_t n)95 void deallocate(T* p, std::size_t n) 96 {std::free(p);} 97 select_on_container_copy_construction()98 other_allocator select_on_container_copy_construction() const 99 {return other_allocator(-2);} 100 101 friend bool operator==(const other_allocator& x, const other_allocator& y) 102 {return x.data_ == y.data_;} 103 friend bool operator!=(const other_allocator& x, const other_allocator& y) 104 {return !(x == y);} 105 106 typedef std::true_type propagate_on_container_copy_assignment; 107 typedef std::true_type propagate_on_container_move_assignment; 108 typedef std::true_type propagate_on_container_swap; 109 110 #ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE max_size()111 std::size_t max_size() const 112 {return UINT_MAX / sizeof(T);} 113 #endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE 114 115 }; 116 117 #endif // TEST_ALLOCATOR_H 118