xref: /llvm-project/libcxx/test/support/allocators.h (revision 2ca101f4b019adafe5fe3545420eaec160bd6e79)
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