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