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