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 // UNSUPPORTED: c++03
10 
11 // <memory>
12 
13 // template <class OuterAlloc, class... InnerAllocs>
14 //   class scoped_allocator_adaptor
15 
16 // template <class T, class... Args> void construct(T* p, Args&&... args);
17 
18 #include <scoped_allocator>
19 #include <cassert>
20 #include <string>
21 
22 #include "test_macros.h"
23 #include "allocators.h"
24 
25 struct B {
26   static bool constructed;
27 
28   typedef A1<B> allocator_type;
29 
BB30   explicit B(std::allocator_arg_t, const allocator_type& a, int i) {
31     assert(a.id() == 5);
32     assert(i == 6);
33     constructed = true;
34   }
35 };
36 
37 bool B::constructed = false;
38 
39 struct C {
40   static bool constructed;
41 
42   typedef std::scoped_allocator_adaptor<A2<C>> allocator_type;
43 
CC44   explicit C(std::allocator_arg_t, const allocator_type& a, int i) {
45     assert(a.id() == 7);
46     assert(i == 8);
47     constructed = true;
48   }
49 };
50 
51 bool C::constructed = false;
52 
53 struct D {
54   static bool constructed;
55 
56   typedef std::scoped_allocator_adaptor<A2<D>> allocator_type;
57 
DD58   explicit D(int i, int j, const allocator_type& a) {
59     assert(i == 1);
60     assert(j == 2);
61     assert(a.id() == 3);
62     constructed = true;
63   }
64 };
65 
66 bool D::constructed = false;
67 
68 struct E {
69   static bool constructed;
70 
71   typedef std::scoped_allocator_adaptor<A1<E>> allocator_type;
72 
EE73   explicit E(int i, int j, const allocator_type& a) {
74     assert(i == 1);
75     assert(j == 2);
76     assert(a.id() == 50);
77     constructed = true;
78   }
79 };
80 
81 bool E::constructed = false;
82 
83 struct F {
84   static bool constructed;
85 
86   typedef std::scoped_allocator_adaptor<A2<F>> allocator_type;
87 
FF88   explicit F(int i, int j) {
89     assert(i == 1);
90     assert(j == 2);
91   }
92 
FF93   explicit F(int i, int j, const allocator_type& a) {
94     assert(i == 1);
95     assert(j == 2);
96     assert(a.id() == 50);
97     constructed = true;
98   }
99 };
100 
101 bool F::constructed = false;
102 
103 struct G {
104   static bool constructed;
105 
106   typedef std::scoped_allocator_adaptor<std::allocator<G>> allocator_type;
107 
GG108   G(std::allocator_arg_t, allocator_type&&) { assert(false); }
GG109   G(const allocator_type&) { constructed = true; }
110 };
111 
112 bool G::constructed = false;
113 
main(int,char **)114 int main(int, char**) {
115   {
116     typedef std::scoped_allocator_adaptor<A1<std::string>> A;
117     A a;
118     char buf[100];
119     typedef std::string S;
120     S* s = (S*)buf;
121     a.construct(s, 4, 'c');
122     assert(*s == "cccc");
123     s->~S();
124   }
125 
126   {
127     typedef std::scoped_allocator_adaptor<A1<B>> A;
128     A a(A1<B>(5));
129     char buf[100];
130     typedef B S;
131     S* s = (S*)buf;
132     a.construct(s, 6);
133     assert(S::constructed);
134     s->~S();
135   }
136 
137   {
138     typedef std::scoped_allocator_adaptor<A1<int>, A2<C>> A;
139     A a(A1<int>(5), A2<C>(7));
140     char buf[100];
141     typedef C S;
142     S* s = (S*)buf;
143     a.construct(s, 8);
144     assert(S::constructed);
145     s->~S();
146   }
147 
148   {
149     typedef std::scoped_allocator_adaptor<A1<int>, A2<D>> A;
150     A a(A1<int>(5), A2<D>(3));
151     char buf[100];
152     typedef D S;
153     S* s = (S*)buf;
154     a.construct(s, 1, 2);
155     assert(S::constructed);
156     s->~S();
157   }
158 
159   {
160     typedef std::scoped_allocator_adaptor<A3<E>, A2<E>> K;
161     typedef std::scoped_allocator_adaptor<K, A1<E>> A;
162     A a(K(), A1<E>(50));
163     char buf[100];
164     typedef E S;
165     S* s               = (S*)buf;
166     A3<E>::constructed = false;
167     a.construct(s, 1, 2);
168     assert(S::constructed);
169     assert(A3<E>::constructed);
170     s->~S();
171   }
172 
173   {
174     typedef std::scoped_allocator_adaptor<A3<F>, A2<F>> K;
175     typedef std::scoped_allocator_adaptor<K, A1<F>> A;
176     A a(K(), A1<F>(50));
177     char buf[100];
178     typedef F S;
179     S* s               = (S*)buf;
180     A3<F>::constructed = false;
181     a.construct(s, 1, 2);
182     assert(!S::constructed);
183     assert(A3<F>::constructed);
184     s->~S();
185   }
186 
187   // LWG 2586
188   // Test that is_constructible uses an lvalue ref so the correct constructor
189   // is picked.
190   {
191     G::allocator_type sa;
192     G* ptr = sa.allocate(1);
193     sa.construct(ptr);
194     assert(G::constructed);
195     sa.deallocate(ptr, 1);
196   }
197 
198   return 0;
199 }
200