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