1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef ALLOCATORS_H 10 #define ALLOCATORS_H 11 12 #include <cstddef> 13 #include <memory> 14 #include <new> 15 #include <type_traits> 16 #include <utility> 17 18 #include "test_macros.h" 19 20 #if TEST_STD_VER >= 11 21 22 template <class T> 23 class A1 24 { 25 int id_; 26 public: id_(id)27 explicit A1(int id = 0) TEST_NOEXCEPT : id_(id) {} 28 29 typedef T value_type; 30 id()31 int id() const {return id_;} 32 33 static bool copy_called; 34 static bool move_called; 35 static bool allocate_called; 36 static std::pair<T*, std::size_t> deallocate_called; 37 A1(const A1 & a)38 A1(const A1& a) TEST_NOEXCEPT : id_(a.id()) {copy_called = true;} A1(A1 && a)39 A1(A1&& a) TEST_NOEXCEPT : id_(a.id()) {move_called = true;} 40 A1& operator=(const A1& a) TEST_NOEXCEPT { id_ = a.id(); copy_called = true; return *this;} 41 A1& operator=(A1&& a) TEST_NOEXCEPT { id_ = a.id(); move_called = true; return *this;} 42 43 template <class U> A1(const A1<U> & a)44 A1(const A1<U>& a) TEST_NOEXCEPT : id_(a.id()) {copy_called = true;} 45 template <class U> A1(A1<U> && a)46 A1(A1<U>&& a) TEST_NOEXCEPT : id_(a.id()) {move_called = true;} 47 allocate(std::size_t n)48 T* allocate(std::size_t n) 49 { 50 allocate_called = true; 51 return (T*)n; 52 } 53 deallocate(T * p,std::size_t n)54 void deallocate(T* p, std::size_t n) 55 { 56 deallocate_called = std::pair<T*, std::size_t>(p, n); 57 } 58 max_size()59 std::size_t max_size() const {return id_;} 60 }; 61 62 template <class T> bool A1<T>::copy_called = false; 63 template <class T> bool A1<T>::move_called = false; 64 template <class T> bool A1<T>::allocate_called = false; 65 template <class T> std::pair<T*, std::size_t> A1<T>::deallocate_called; 66 67 template <class T, class U> 68 inline 69 bool operator==(const A1<T>& x, const A1<U>& y) 70 { 71 return x.id() == y.id(); 72 } 73 74 template <class T, class U> 75 inline 76 bool operator!=(const A1<T>& x, const A1<U>& y) 77 { 78 return !(x == y); 79 } 80 81 template <class T> 82 class A2 83 { 84 int id_; 85 public: id_(id)86 explicit A2(int id = 0) TEST_NOEXCEPT : id_(id) {} 87 88 typedef T value_type; 89 90 typedef unsigned size_type; 91 typedef int difference_type; 92 93 typedef std::true_type propagate_on_container_move_assignment; 94 id()95 int id() const {return id_;} 96 97 static bool copy_called; 98 static bool move_called; 99 static bool allocate_called; 100 A2(const A2 & a)101 A2(const A2& a) TEST_NOEXCEPT : id_(a.id()) {copy_called = true;} A2(A2 && a)102 A2(A2&& a) TEST_NOEXCEPT : id_(a.id()) {move_called = true;} 103 A2& operator=(const A2& a) TEST_NOEXCEPT { id_ = a.id(); copy_called = true; return *this;} 104 A2& operator=(A2&& a) TEST_NOEXCEPT { id_ = a.id(); move_called = true; return *this;} 105 allocate(std::size_t,const void * hint)106 T* allocate(std::size_t, const void* hint) 107 { 108 allocate_called = true; 109 return (T*) const_cast<void *>(hint); 110 } 111 }; 112 113 template <class T> bool A2<T>::copy_called = false; 114 template <class T> bool A2<T>::move_called = false; 115 template <class T> bool A2<T>::allocate_called = false; 116 117 template <class T, class U> 118 inline 119 bool operator==(const A2<T>& x, const A2<U>& y) 120 { 121 return x.id() == y.id(); 122 } 123 124 template <class T, class U> 125 inline 126 bool operator!=(const A2<T>& x, const A2<U>& y) 127 { 128 return !(x == y); 129 } 130 131 template <class T> 132 class A3 133 { 134 int id_; 135 public: id_(id)136 explicit A3(int id = 0) TEST_NOEXCEPT : id_(id) {} 137 138 typedef T value_type; 139 140 typedef std::true_type propagate_on_container_copy_assignment; 141 typedef std::true_type propagate_on_container_swap; 142 id()143 int id() const {return id_;} 144 145 static bool copy_called; 146 static bool move_called; 147 static bool constructed; 148 static bool destroy_called; 149 A3(const A3 & a)150 A3(const A3& a) TEST_NOEXCEPT : id_(a.id()) {copy_called = true;} A3(A3 && a)151 A3(A3&& a) TEST_NOEXCEPT : id_(a.id()) {move_called = true;} 152 A3& operator=(const A3& a) TEST_NOEXCEPT { id_ = a.id(); copy_called = true; return *this;} 153 A3& operator=(A3&& a) TEST_NOEXCEPT { id_ = a.id(); move_called = true; return *this;} 154 155 template <class U, class ...Args> construct(U * p,Args &&...args)156 void construct(U* p, Args&& ...args) 157 { 158 ::new (p) U(std::forward<Args>(args)...); 159 constructed = true; 160 } 161 162 template <class U> destroy(U * p)163 void destroy(U* p) 164 { 165 p->~U(); 166 destroy_called = true; 167 } 168 select_on_container_copy_construction()169 A3 select_on_container_copy_construction() const {return A3(-1);} 170 }; 171 172 template <class T> bool A3<T>::copy_called = false; 173 template <class T> bool A3<T>::move_called = false; 174 template <class T> bool A3<T>::constructed = false; 175 template <class T> bool A3<T>::destroy_called = false; 176 177 template <class T, class U> 178 inline 179 bool operator==(const A3<T>& x, const A3<U>& y) 180 { 181 return x.id() == y.id(); 182 } 183 184 template <class T, class U> 185 inline 186 bool operator!=(const A3<T>& x, const A3<U>& y) 187 { 188 return !(x == y); 189 } 190 191 template <class T, bool POCCAValue> 192 class MaybePOCCAAllocator { 193 int id_ = 0; 194 bool* copy_assigned_into_ = nullptr; 195 196 template<class, bool> friend class MaybePOCCAAllocator; 197 198 public: 199 typedef std::integral_constant<bool, POCCAValue> propagate_on_container_copy_assignment; 200 typedef T value_type; 201 202 template <class U> 203 struct rebind { 204 typedef MaybePOCCAAllocator<U, POCCAValue> other; 205 }; 206 207 TEST_CONSTEXPR MaybePOCCAAllocator() = default; MaybePOCCAAllocator(int id,bool * copy_assigned_into)208 TEST_CONSTEXPR MaybePOCCAAllocator(int id, bool* copy_assigned_into) 209 : id_(id), copy_assigned_into_(copy_assigned_into) {} 210 211 template <class U> MaybePOCCAAllocator(const MaybePOCCAAllocator<U,POCCAValue> & that)212 TEST_CONSTEXPR MaybePOCCAAllocator(const MaybePOCCAAllocator<U, POCCAValue>& that) 213 : id_(that.id_), copy_assigned_into_(that.copy_assigned_into_) {} 214 215 MaybePOCCAAllocator(const MaybePOCCAAllocator&) = default; 216 TEST_CONSTEXPR_CXX14 MaybePOCCAAllocator& operator=(const MaybePOCCAAllocator& a) 217 { 218 id_ = a.id(); 219 if (copy_assigned_into_) 220 *copy_assigned_into_ = true; 221 return *this; 222 } 223 allocate(std::size_t n)224 TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) 225 { 226 return std::allocator<T>().allocate(n); 227 } 228 deallocate(T * ptr,std::size_t n)229 TEST_CONSTEXPR_CXX20 void deallocate(T* ptr, std::size_t n) 230 { 231 std::allocator<T>().deallocate(ptr, n); 232 } 233 id()234 TEST_CONSTEXPR int id() const { return id_; } 235 236 template <class U> 237 TEST_CONSTEXPR friend bool operator==(const MaybePOCCAAllocator& lhs, const MaybePOCCAAllocator<U, POCCAValue>& rhs) 238 { 239 return lhs.id() == rhs.id(); 240 } 241 242 template <class U> 243 TEST_CONSTEXPR friend bool operator!=(const MaybePOCCAAllocator& lhs, const MaybePOCCAAllocator<U, POCCAValue>& rhs) 244 { 245 return !(lhs == rhs); 246 } 247 }; 248 249 template <class T> 250 using POCCAAllocator = MaybePOCCAAllocator<T, /*POCCAValue = */true>; 251 template <class T> 252 using NonPOCCAAllocator = MaybePOCCAAllocator<T, /*POCCAValue = */false>; 253 254 #endif // TEST_STD_VER >= 11 255 256 #endif // ALLOCATORS_H 257