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// template <class Alloc>
12// struct allocator_traits
13// {
14// template <class Ptr>
15// static constexpr void destroy(allocator_type& a, Ptr p);
16// ...
17// };
18
19#include <memory>
20#include <cassert>
21#include <cstddef>
22
23#include "test_macros.h"
24#include "incomplete_type_helper.h"
25
26template <class T>
27struct NoDestroy
28{
29 typedef T value_type;
30
31 TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n)
32 {
33 return std::allocator<T>().allocate(n);
34 }
35
36 TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t n)
37 {
38 return std::allocator<T>().deallocate(p, n);
39 }
40};
41
42template <class T>
43struct CountDestroy
44{
45 TEST_CONSTEXPR explicit CountDestroy(int* counter)
46 : counter_(counter)
47 { }
48
49 typedef T value_type;
50
51 TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n)
52 {
53 return std::allocator<T>().allocate(n);
54 }
55
56 TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t n)
57 {
58 return std::allocator<T>().deallocate(p, n);
59 }
60
61 template <class U>
62 TEST_CONSTEXPR_CXX20 void destroy(U* p)
63 {
64 ++*counter_;
65 p->~U();
66 }
67
68 int* counter_;
69};
70
71struct CountDestructor
72{
73 TEST_CONSTEXPR explicit CountDestructor(int* counter)
74 : counter_(counter)
75 { }
76
77 TEST_CONSTEXPR_CXX20 ~CountDestructor() { ++*counter_; }
78
79 int* counter_;
80};
81
82TEST_CONSTEXPR_CXX20 bool test()
83{
84 {
85 typedef NoDestroy<CountDestructor> Alloc;
86 int destructors = 0;
87 Alloc alloc;
88 CountDestructor* pool = std::allocator_traits<Alloc>::allocate(alloc, 1);
89
90 std::allocator_traits<Alloc>::construct(alloc, pool, &destructors);
91 assert(destructors == 0);
92
93 std::allocator_traits<Alloc>::destroy(alloc, pool);
94 assert(destructors == 1);
95
96 std::allocator_traits<Alloc>::deallocate(a&: alloc, p: pool, n: 1);
97 }
98 {
99 typedef IncompleteHolder* T;
100 typedef NoDestroy<T> Alloc;
101 Alloc alloc;
102 T* pool = std::allocator_traits<Alloc>::allocate(alloc, 1);
103 std::allocator_traits<Alloc>::construct(alloc, pool, nullptr);
104 std::allocator_traits<Alloc>::destroy(alloc, pool);
105 std::allocator_traits<Alloc>::deallocate(a&: alloc, p: pool, n: 1);
106 }
107 {
108 typedef CountDestroy<CountDestructor> Alloc;
109 int destroys_called = 0;
110 int destructors_called = 0;
111 Alloc alloc(&destroys_called);
112
113 CountDestructor* pool = std::allocator_traits<Alloc>::allocate(alloc, 1);
114 std::allocator_traits<Alloc>::construct(alloc, pool, &destructors_called);
115 assert(destroys_called == 0);
116 assert(destructors_called == 0);
117
118 std::allocator_traits<Alloc>::destroy(alloc, pool);
119 assert(destroys_called == 1);
120 assert(destructors_called == 1);
121
122 std::allocator_traits<Alloc>::deallocate(a&: alloc, p: pool, n: 1);
123 }
124 return true;
125}
126
127int main(int, char**)
128{
129 test();
130#if TEST_STD_VER > 17
131 static_assert(test());
132#endif
133 return 0;
134}
135

source code of libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp