xref: /llvm-project/libcxx/test/support/deleter_types.h (revision 70248920fcd804a5825ecf69f24b96a7e340afe6)
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 // <memory>
10 
11 // unique_ptr
12 
13 // Example move-only deleter
14 
15 #ifndef SUPPORT_DELETER_TYPES_H
16 #define SUPPORT_DELETER_TYPES_H
17 
18 #include <cstddef>
19 #include <type_traits>
20 #include <utility>
21 #include <cassert>
22 
23 #include "test_macros.h"
24 #include "min_allocator.h"
25 
26 #if TEST_STD_VER >= 11
27 
28 template <class T>
29 class Deleter {
30   int state_;
31 
32   Deleter(const Deleter&);
33   Deleter& operator=(const Deleter&);
34 
35 public:
Deleter(Deleter && r)36   TEST_CONSTEXPR_CXX23 Deleter(Deleter&& r) : state_(r.state_) { r.state_ = 0; }
37   TEST_CONSTEXPR_CXX23 Deleter& operator=(Deleter&& r) {
38     state_   = r.state_;
39     r.state_ = 0;
40     return *this;
41   }
42 
Deleter()43   TEST_CONSTEXPR_CXX23 Deleter() : state_(0) {}
Deleter(int s)44   TEST_CONSTEXPR_CXX23 explicit Deleter(int s) : state_(s) {}
~Deleter()45   TEST_CONSTEXPR_CXX23 ~Deleter() {
46     assert(state_ >= 0);
47     state_ = -1;
48   }
49 
50   template <class U>
51   TEST_CONSTEXPR_CXX23 Deleter(Deleter<U>&& d, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
52       : state_(d.state()) {
53     d.set_state(0);
54   }
55 
56 private:
57   template <class U>
58   Deleter(const Deleter<U>& d, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
59 
60 public:
state()61   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)62   TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
63 
operator()64   TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; }
65 };
66 
67 template <class T>
68 class Deleter<T[]> {
69   int state_;
70 
71   Deleter(const Deleter&);
72   Deleter& operator=(const Deleter&);
73 
74 public:
Deleter(Deleter && r)75   TEST_CONSTEXPR_CXX23 Deleter(Deleter&& r) : state_(r.state_) { r.state_ = 0; }
76   TEST_CONSTEXPR_CXX23 Deleter& operator=(Deleter&& r) {
77     state_   = r.state_;
78     r.state_ = 0;
79     return *this;
80   }
81 
Deleter()82   TEST_CONSTEXPR_CXX23 Deleter() : state_(0) {}
Deleter(int s)83   TEST_CONSTEXPR_CXX23 explicit Deleter(int s) : state_(s) {}
~Deleter()84   TEST_CONSTEXPR_CXX23 ~Deleter() {
85     assert(state_ >= 0);
86     state_ = -1;
87   }
88 
state()89   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)90   TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
91 
operator()92   TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; }
93 };
94 
95 #else // TEST_STD_VER < 11
96 
97 template <class T>
98 class Deleter {
99   mutable int state_;
100 
101 public:
Deleter()102   Deleter() : state_(0) {}
Deleter(int s)103   explicit Deleter(int s) : state_(s) {}
104 
Deleter(Deleter const & other)105   Deleter(Deleter const& other) : state_(other.state_) { other.state_ = 0; }
106   Deleter& operator=(Deleter const& other) {
107     state_       = other.state_;
108     other.state_ = 0;
109     return *this;
110   }
111 
~Deleter()112   ~Deleter() {
113     assert(state_ >= 0);
114     state_ = -1;
115   }
116 
117   template <class U>
118   Deleter(Deleter<U> d, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) : state_(d.state()) {}
119 
120 public:
state()121   int state() const { return state_; }
set_state(int i)122   void set_state(int i) { state_ = i; }
123 
operator()124   void operator()(T* p) { delete p; }
125 };
126 
127 template <class T>
128 class Deleter<T[]> {
129   mutable int state_;
130 
131 public:
Deleter(Deleter const & other)132   Deleter(Deleter const& other) : state_(other.state_) { other.state_ = 0; }
133   Deleter& operator=(Deleter const& other) {
134     state_       = other.state_;
135     other.state_ = 0;
136     return *this;
137   }
138 
Deleter()139   Deleter() : state_(0) {}
Deleter(int s)140   explicit Deleter(int s) : state_(s) {}
~Deleter()141   ~Deleter() {
142     assert(state_ >= 0);
143     state_ = -1;
144   }
145 
state()146   int state() const { return state_; }
set_state(int i)147   void set_state(int i) { state_ = i; }
148 
operator()149   void operator()(T* p) { delete[] p; }
150 };
151 
152 #endif
153 
154 template <class T>
swap(Deleter<T> & x,Deleter<T> & y)155 TEST_CONSTEXPR_CXX23 void swap(Deleter<T>& x, Deleter<T>& y) {
156   Deleter<T> t(std::move(x));
157   x = std::move(y);
158   y = std::move(t);
159 }
160 
161 template <class T>
162 class CDeleter {
163   int state_;
164 
165 public:
CDeleter()166   TEST_CONSTEXPR_CXX23 CDeleter() : state_(0) {}
CDeleter(int s)167   TEST_CONSTEXPR_CXX23 explicit CDeleter(int s) : state_(s) {}
168   TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter&) = default;
169   TEST_CONSTEXPR_CXX23 CDeleter& operator=(const CDeleter&) = default;
~CDeleter()170   TEST_CONSTEXPR_CXX23 ~CDeleter() {
171     assert(state_ >= 0);
172     state_ = -1;
173   }
174 
175   template <class U>
CDeleter(const CDeleter<U> & d)176   TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter<U>& d) : state_(d.state()) {}
177 
state()178   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)179   TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
180 
operator()181   TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; }
182 };
183 
184 template <class T>
185 class CDeleter<T[]> {
186   int state_;
187 
188 public:
CDeleter()189   TEST_CONSTEXPR_CXX23 CDeleter() : state_(0) {}
CDeleter(int s)190   TEST_CONSTEXPR_CXX23 explicit CDeleter(int s) : state_(s) {}
191   template <class U>
CDeleter(const CDeleter<U> & d)192   TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter<U>& d) : state_(d.state()) {}
193   TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter&) = default;
194   TEST_CONSTEXPR_CXX23 CDeleter& operator=(const CDeleter&) = default;
~CDeleter()195   TEST_CONSTEXPR_CXX23 ~CDeleter() {
196     assert(state_ >= 0);
197     state_ = -1;
198   }
199 
state()200   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)201   TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
202 
operator()203   TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; }
204 };
205 
206 template <class T>
swap(CDeleter<T> & x,CDeleter<T> & y)207 TEST_CONSTEXPR_CXX23 void swap(CDeleter<T>& x, CDeleter<T>& y) {
208   CDeleter<T> t(std::move(x));
209   x = std::move(y);
210   y = std::move(t);
211 }
212 
213 // Non-copyable deleter
214 template <class T>
215 class NCDeleter {
216   int state_;
217   NCDeleter(NCDeleter const&);
218   NCDeleter& operator=(NCDeleter const&);
219 
220 public:
NCDeleter()221   TEST_CONSTEXPR_CXX23 NCDeleter() : state_(0) {}
NCDeleter(int s)222   TEST_CONSTEXPR_CXX23 explicit NCDeleter(int s) : state_(s) {}
~NCDeleter()223   TEST_CONSTEXPR_CXX23 ~NCDeleter() {
224     assert(state_ >= 0);
225     state_ = -1;
226   }
227 
state()228   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)229   TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
230 
operator()231   TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; }
232 };
233 
234 template <class T>
235 class NCDeleter<T[]> {
236   int state_;
237   NCDeleter(NCDeleter const&);
238   NCDeleter& operator=(NCDeleter const&);
239 
240 public:
NCDeleter()241   TEST_CONSTEXPR_CXX23 NCDeleter() : state_(0) {}
NCDeleter(int s)242   TEST_CONSTEXPR_CXX23 explicit NCDeleter(int s) : state_(s) {}
~NCDeleter()243   TEST_CONSTEXPR_CXX23 ~NCDeleter() {
244     assert(state_ >= 0);
245     state_ = -1;
246   }
247 
state()248   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)249   TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
250 
operator()251   TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; }
252 };
253 
254 // Non-copyable deleter
255 template <class T>
256 class NCConstDeleter {
257   int state_;
258   NCConstDeleter(NCConstDeleter const&);
259   NCConstDeleter& operator=(NCConstDeleter const&);
260 
261 public:
NCConstDeleter()262   TEST_CONSTEXPR_CXX23 NCConstDeleter() : state_(0) {}
NCConstDeleter(int s)263   TEST_CONSTEXPR_CXX23 explicit NCConstDeleter(int s) : state_(s) {}
~NCConstDeleter()264   TEST_CONSTEXPR_CXX23 ~NCConstDeleter() {
265     assert(state_ >= 0);
266     state_ = -1;
267   }
268 
state()269   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)270   TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
271 
operator()272   TEST_CONSTEXPR_CXX23 void operator()(T* p) const { delete p; }
273 };
274 
275 template <class T>
276 class NCConstDeleter<T[]> {
277   int state_;
278   NCConstDeleter(NCConstDeleter const&);
279   NCConstDeleter& operator=(NCConstDeleter const&);
280 
281 public:
NCConstDeleter()282   TEST_CONSTEXPR_CXX23 NCConstDeleter() : state_(0) {}
NCConstDeleter(int s)283   TEST_CONSTEXPR_CXX23 explicit NCConstDeleter(int s) : state_(s) {}
~NCConstDeleter()284   TEST_CONSTEXPR_CXX23 ~NCConstDeleter() {
285     assert(state_ >= 0);
286     state_ = -1;
287   }
288 
state()289   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)290   TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
291 
operator()292   TEST_CONSTEXPR_CXX23 void operator()(T* p) const { delete[] p; }
293 };
294 
295 // Non-copyable deleter
296 template <class T>
297 class CopyDeleter {
298   int state_;
299 
300 public:
CopyDeleter()301   TEST_CONSTEXPR_CXX23 CopyDeleter() : state_(0) {}
CopyDeleter(int s)302   TEST_CONSTEXPR_CXX23 explicit CopyDeleter(int s) : state_(s) {}
~CopyDeleter()303   TEST_CONSTEXPR_CXX23 ~CopyDeleter() {
304     assert(state_ >= 0);
305     state_ = -1;
306   }
307 
CopyDeleter(CopyDeleter const & other)308   TEST_CONSTEXPR_CXX23 CopyDeleter(CopyDeleter const& other) : state_(other.state_) {}
309   TEST_CONSTEXPR_CXX23 CopyDeleter& operator=(CopyDeleter const& other) {
310     state_ = other.state_;
311     return *this;
312   }
313 
state()314   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)315   TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
316 
operator()317   TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; }
318 };
319 
320 template <class T>
321 class CopyDeleter<T[]> {
322   int state_;
323 
324 public:
CopyDeleter()325   TEST_CONSTEXPR_CXX23 CopyDeleter() : state_(0) {}
CopyDeleter(int s)326   TEST_CONSTEXPR_CXX23 explicit CopyDeleter(int s) : state_(s) {}
~CopyDeleter()327   TEST_CONSTEXPR_CXX23 ~CopyDeleter() {
328     assert(state_ >= 0);
329     state_ = -1;
330   }
331 
CopyDeleter(CopyDeleter const & other)332   TEST_CONSTEXPR_CXX23 CopyDeleter(CopyDeleter const& other) : state_(other.state_) {}
333   TEST_CONSTEXPR_CXX23 CopyDeleter& operator=(CopyDeleter const& other) {
334     state_ = other.state_;
335     return *this;
336   }
337 
state()338   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
set_state(int i)339   TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; }
340 
operator()341   TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; }
342 };
343 
344 struct test_deleter_base {
345   static int count;
346   static int dealloc_count;
347 };
348 
349 int test_deleter_base::count         = 0;
350 int test_deleter_base::dealloc_count = 0;
351 
352 template <class T>
353 class test_deleter : public test_deleter_base {
354   int state_;
355 
356 public:
test_deleter()357   test_deleter() : state_(0) { ++count; }
test_deleter(int s)358   explicit test_deleter(int s) : state_(s) { ++count; }
test_deleter(const test_deleter & d)359   test_deleter(const test_deleter& d) : state_(d.state_) { ++count; }
~test_deleter()360   ~test_deleter() {
361     assert(state_ >= 0);
362     --count;
363     state_ = -1;
364   }
365 
state()366   int state() const { return state_; }
set_state(int i)367   void set_state(int i) { state_ = i; }
368 
operator()369   void operator()(T* p) {
370     assert(state_ >= 0);
371     ++dealloc_count;
372     delete p;
373   }
374 #if TEST_STD_VER >= 11
375   test_deleter* operator&() const = delete;
376 #else
377 
378 private:
379   test_deleter* operator&() const;
380 #endif
381 };
382 
383 template <class T>
swap(test_deleter<T> & x,test_deleter<T> & y)384 void swap(test_deleter<T>& x, test_deleter<T>& y) {
385   test_deleter<T> t(std::move(x));
386   x = std::move(y);
387   y = std::move(t);
388 }
389 
390 #if TEST_STD_VER >= 11
391 
392 template <class T, std::size_t ID = 0>
393 class PointerDeleter {
394   PointerDeleter(const PointerDeleter&);
395   PointerDeleter& operator=(const PointerDeleter&);
396 
397 public:
398   typedef min_pointer<T, std::integral_constant<std::size_t, ID>> pointer;
399 
400   TEST_CONSTEXPR_CXX23 PointerDeleter()                            = default;
401   TEST_CONSTEXPR_CXX23 PointerDeleter(PointerDeleter&&)            = default;
402   TEST_CONSTEXPR_CXX23 PointerDeleter& operator=(PointerDeleter&&) = default;
PointerDeleter(int)403   TEST_CONSTEXPR_CXX23 explicit PointerDeleter(int) {}
404 
405   template <class U>
406   TEST_CONSTEXPR_CXX23
407   PointerDeleter(PointerDeleter<U, ID>&&, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) {}
408 
operator()409   TEST_CONSTEXPR_CXX23 void operator()(pointer p) {
410     if (p) {
411       delete std::addressof(*p);
412     }
413   }
414 
415 private:
416   template <class U>
417   PointerDeleter(const PointerDeleter<U, ID>&, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
418 };
419 
420 template <class T, std::size_t ID>
421 class PointerDeleter<T[], ID> {
422   PointerDeleter(const PointerDeleter&);
423   PointerDeleter& operator=(const PointerDeleter&);
424 
425 public:
426   typedef min_pointer<T, std::integral_constant<std::size_t, ID> > pointer;
427 
428   TEST_CONSTEXPR_CXX23 PointerDeleter()                            = default;
429   TEST_CONSTEXPR_CXX23 PointerDeleter(PointerDeleter&&)            = default;
430   TEST_CONSTEXPR_CXX23 PointerDeleter& operator=(PointerDeleter&&) = default;
PointerDeleter(int)431   TEST_CONSTEXPR_CXX23 explicit PointerDeleter(int) {}
432 
433   template <class U>
434   TEST_CONSTEXPR_CXX23
435   PointerDeleter(PointerDeleter<U, ID>&&, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) {}
436 
operator()437   TEST_CONSTEXPR_CXX23 void operator()(pointer p) {
438     if (p) {
439       delete[] std::addressof(*p);
440     }
441   }
442 
443 private:
444   template <class U>
445   PointerDeleter(const PointerDeleter<U, ID>&, typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
446 };
447 
448 #endif // TEST_STD_VER >= 11
449 
450 template <class T>
451 class DefaultCtorDeleter {
452   int state_;
453 
454 public:
state()455   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
operator()456   TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; }
457 };
458 
459 template <class T>
460 class DefaultCtorDeleter<T[]> {
461   int state_;
462 
463 public:
state()464   TEST_CONSTEXPR_CXX23 int state() const { return state_; }
operator()465   TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; }
466 };
467 
468 #endif // SUPPORT_DELETER_TYPES_H
469