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