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 public: 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 40 test_allocator() throw() : data_(-1) {} 41 explicit test_allocator(int i) throw() : data_(i) {} 42 test_allocator(const test_allocator& a) throw() 43 : data_(a.data_) {} 44 template <class U> test_allocator(const test_allocator<U>& a) throw() 45 : data_(a.data_) {} 46 ~test_allocator() throw() {data_ = 0;} 47 pointer address(reference x) const {return &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 } 61 void deallocate(pointer p, size_type n) 62 {--count; std::free(p);} 63 size_type max_size() const throw() 64 {return UINT_MAX / sizeof(T);} 65 void construct(pointer p, const T& val) 66 {::new(p) T(val);} 67 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 68 void construct(pointer p, T&& val) 69 {::new(p) T(std::move(val));} 70 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 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 <> 80 class test_allocator<void> 81 : public test_alloc_base 82 { 83 int data_; 84 85 template <class U> friend class test_allocator; 86 public: 87 88 typedef unsigned size_type; 89 typedef int difference_type; 90 typedef void value_type; 91 typedef value_type* pointer; 92 typedef const value_type* const_pointer; 93 94 template <class U> struct rebind {typedef test_allocator<U> other;}; 95 96 test_allocator() throw() : data_(-1) {} 97 explicit test_allocator(int i) throw() : data_(i) {} 98 test_allocator(const test_allocator& a) throw() 99 : data_(a.data_) {} 100 template <class U> test_allocator(const test_allocator<U>& a) throw() 101 : data_(a.data_) {} 102 ~test_allocator() throw() {data_ = 0;} 103 104 friend bool operator==(const test_allocator& x, const test_allocator& y) 105 {return x.data_ == y.data_;} 106 friend bool operator!=(const test_allocator& x, const test_allocator& y) 107 {return !(x == y);} 108 }; 109 110 template <class T> 111 class other_allocator 112 { 113 int data_; 114 115 template <class U> friend class other_allocator; 116 117 public: 118 typedef T value_type; 119 120 other_allocator() : data_(-1) {} 121 explicit other_allocator(int i) : data_(i) {} 122 template <class U> other_allocator(const other_allocator<U>& a) 123 : data_(a.data_) {} 124 T* allocate(std::size_t n) 125 {return (T*)std::malloc(n * sizeof(T));} 126 void deallocate(T* p, std::size_t n) 127 {std::free(p);} 128 129 other_allocator select_on_container_copy_construction() const 130 {return other_allocator(-2);} 131 132 friend bool operator==(const other_allocator& x, const other_allocator& y) 133 {return x.data_ == y.data_;} 134 friend bool operator!=(const other_allocator& x, const other_allocator& y) 135 {return !(x == y);} 136 137 typedef std::true_type propagate_on_container_copy_assignment; 138 typedef std::true_type propagate_on_container_move_assignment; 139 typedef std::true_type propagate_on_container_swap; 140 141 #ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE 142 std::size_t max_size() const 143 {return UINT_MAX / sizeof(T);} 144 #endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE 145 146 }; 147 148 #endif // TEST_ALLOCATOR_H 149