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, class... Args> |
15 | // static constexpr void construct(allocator_type& a, Ptr p, Args&&... args); |
16 | // ... |
17 | // }; |
18 | |
19 | #include <memory> |
20 | #include <new> |
21 | #include <type_traits> |
22 | #include <cassert> |
23 | #include <utility> |
24 | |
25 | #include "test_macros.h" |
26 | #include "incomplete_type_helper.h" |
27 | |
28 | template <class T> |
29 | struct A |
30 | { |
31 | typedef T value_type; |
32 | |
33 | }; |
34 | |
35 | template <class T> |
36 | struct B |
37 | { |
38 | typedef T value_type; |
39 | |
40 | TEST_CONSTEXPR_CXX20 B(int& count) : count_(count) {} |
41 | |
42 | #if TEST_STD_VER >= 11 |
43 | template <class U, class ...Args> |
44 | TEST_CONSTEXPR_CXX20 void construct(U* p, Args&& ...args) |
45 | { |
46 | ++count_; |
47 | #if TEST_STD_VER > 17 |
48 | std::construct_at(p, std::forward<Args>(args)...); |
49 | #else |
50 | ::new ((void*)p) U(std::forward<Args>(args)...); |
51 | #endif |
52 | } |
53 | #endif |
54 | |
55 | int& count_; |
56 | }; |
57 | |
58 | struct A0 |
59 | { |
60 | TEST_CONSTEXPR_CXX20 A0(int* count) {++*count;} |
61 | }; |
62 | |
63 | struct A1 |
64 | { |
65 | TEST_CONSTEXPR_CXX20 A1(int* count, char c) |
66 | { |
67 | assert(c == 'c'); |
68 | ++*count; |
69 | } |
70 | }; |
71 | |
72 | struct A2 |
73 | { |
74 | TEST_CONSTEXPR_CXX20 A2(int* count, char c, int i) |
75 | { |
76 | assert(c == 'd'); |
77 | assert(i == 5); |
78 | ++*count; |
79 | } |
80 | }; |
81 | |
82 | TEST_CONSTEXPR_CXX20 bool test() |
83 | { |
84 | { |
85 | int A0_count = 0; |
86 | A<A0> a; |
87 | std::allocator<A0> alloc; |
88 | A0* a0 = alloc.allocate(n: 1); |
89 | assert(A0_count == 0); |
90 | std::allocator_traits<A<A0> >::construct(a, a0, &A0_count); |
91 | assert(A0_count == 1); |
92 | alloc.deallocate(p: a0, t: 1); |
93 | } |
94 | { |
95 | int A1_count = 0; |
96 | A<A1> a; |
97 | std::allocator<A1> alloc; |
98 | A1* a1 = alloc.allocate(n: 1); |
99 | assert(A1_count == 0); |
100 | std::allocator_traits<A<A1> >::construct(a, a1, &A1_count, 'c'); |
101 | assert(A1_count == 1); |
102 | alloc.deallocate(p: a1, t: 1); |
103 | } |
104 | { |
105 | int A2_count = 0; |
106 | A<A2> a; |
107 | std::allocator<A2> alloc; |
108 | A2* a2 = alloc.allocate(n: 1); |
109 | assert(A2_count == 0); |
110 | std::allocator_traits<A<A2> >::construct(a, a2, &A2_count, 'd', 5); |
111 | assert(A2_count == 1); |
112 | alloc.deallocate(p: a2, t: 1); |
113 | } |
114 | { |
115 | typedef IncompleteHolder* VT; |
116 | typedef A<VT> Alloc; |
117 | Alloc a; |
118 | std::allocator<VT> alloc; |
119 | VT* vt = alloc.allocate(n: 1); |
120 | std::allocator_traits<Alloc>::construct(a&: a, p: vt, args: nullptr); |
121 | alloc.deallocate(p: vt, t: 1); |
122 | } |
123 | |
124 | #if TEST_STD_VER >= 11 |
125 | { |
126 | int A0_count = 0; |
127 | int b_construct = 0; |
128 | B<A0> b(b_construct); |
129 | std::allocator<A0> alloc; |
130 | A0* a0 = alloc.allocate(1); |
131 | assert(A0_count == 0); |
132 | assert(b_construct == 0); |
133 | std::allocator_traits<B<A0> >::construct(b, a0, &A0_count); |
134 | assert(A0_count == 1); |
135 | assert(b_construct == 1); |
136 | alloc.deallocate(a0, 1); |
137 | } |
138 | { |
139 | int A1_count = 0; |
140 | int b_construct = 0; |
141 | B<A1> b(b_construct); |
142 | std::allocator<A1> alloc; |
143 | A1* a1 = alloc.allocate(1); |
144 | assert(A1_count == 0); |
145 | assert(b_construct == 0); |
146 | std::allocator_traits<B<A1> >::construct(b, a1, &A1_count, 'c'); |
147 | assert(A1_count == 1); |
148 | assert(b_construct == 1); |
149 | alloc.deallocate(a1, 1); |
150 | } |
151 | { |
152 | int A2_count = 0; |
153 | int b_construct = 0; |
154 | B<A2> b(b_construct); |
155 | std::allocator<A2> alloc; |
156 | A2* a2 = alloc.allocate(1); |
157 | assert(A2_count == 0); |
158 | assert(b_construct == 0); |
159 | std::allocator_traits<B<A2> >::construct(b, a2, &A2_count, 'd', 5); |
160 | assert(A2_count == 1); |
161 | assert(b_construct == 1); |
162 | alloc.deallocate(a2, 1); |
163 | } |
164 | #endif |
165 | |
166 | return true; |
167 | } |
168 | |
169 | int main(int, char**) |
170 | { |
171 | test(); |
172 | |
173 | #if TEST_STD_VER > 17 |
174 | static_assert(test()); |
175 | #endif |
176 | |
177 | return 0; |
178 | } |
179 | |