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 // <scoped_allocator>
12 
13 // template <class OtherAlloc, class ...InnerAlloc>
14 //   class scoped_allocator_adaptor
15 
16 // template <class U1, class U2>
17 // void scoped_allocator_adaptor::construct(pair<U1, U2>*)
18 
19 #include <scoped_allocator>
20 #include <type_traits>
21 #include <utility>
22 #include <tuple>
23 #include <cassert>
24 #include <cstdlib>
25 #include "uses_alloc_types.h"
26 #include "controlled_allocators.h"
27 
28 #include "test_macros.h"
29 
test_no_inner_alloc()30 void test_no_inner_alloc() {
31   using VoidAlloc = CountingAllocator<void>;
32   AllocController P;
33   {
34     using T     = UsesAllocatorV1<VoidAlloc, 0>;
35     using U     = UsesAllocatorV2<VoidAlloc, 0>;
36     using Pair  = std::pair<T, U>;
37     using Alloc = CountingAllocator<Pair>;
38     using SA    = std::scoped_allocator_adaptor<Alloc>;
39     static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, "");
40     Pair* ptr = (Pair*)std::malloc(sizeof(Pair));
41     assert(ptr);
42     Alloc CA(P);
43     SA A(CA);
44     A.construct(ptr);
45     assert(checkConstruct<>(ptr->first, UA_AllocArg, CA));
46     assert(checkConstruct<>(ptr->second, UA_AllocLast, CA));
47 #if TEST_STD_VER >= 20
48     assert((P.checkConstruct<std::piecewise_construct_t&&,
49                              std::tuple<std::allocator_arg_t, const SA&>&&,
50                              std::tuple<const SA&>&& >(CA, ptr)));
51 #else
52     assert((P.checkConstruct<std::piecewise_construct_t const&,
53                              std::tuple<std::allocator_arg_t, SA&>&&,
54                              std::tuple<SA&>&& >(CA, ptr)));
55 #endif
56     A.destroy(ptr);
57     std::free(ptr);
58   }
59   P.reset();
60   {
61     using T     = UsesAllocatorV3<VoidAlloc, 0>;
62     using U     = NotUsesAllocator<VoidAlloc, 0>;
63     using Pair  = std::pair<T, U>;
64     using Alloc = CountingAllocator<Pair>;
65     using SA    = std::scoped_allocator_adaptor<Alloc>;
66     static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, "");
67     Pair* ptr = (Pair*)std::malloc(sizeof(Pair));
68     assert(ptr);
69     Alloc CA(P);
70     SA A(CA);
71     A.construct(ptr);
72     assert(checkConstruct<>(ptr->first, UA_AllocArg, CA));
73     assert(checkConstruct<>(ptr->second, UA_None));
74 #if TEST_STD_VER >= 20
75     assert(
76         (P.checkConstruct<std::piecewise_construct_t&&, std::tuple<std::allocator_arg_t, const SA&>&&, std::tuple<>&& >(
77             CA, ptr)));
78 #else
79     assert(
80         (P.checkConstruct<std::piecewise_construct_t const&, std::tuple<std::allocator_arg_t, SA&>&&, std::tuple<>&& >(
81             CA, ptr)));
82 #endif
83     A.destroy(ptr);
84     std::free(ptr);
85   }
86 }
87 
test_with_inner_alloc()88 void test_with_inner_alloc() {
89   using VoidAlloc2 = CountingAllocator<void, 2>;
90 
91   AllocController POuter;
92   AllocController PInner;
93   {
94     using T       = UsesAllocatorV1<VoidAlloc2, 0>;
95     using U       = UsesAllocatorV2<VoidAlloc2, 0>;
96     using Pair    = std::pair<T, U>;
97     using Outer   = CountingAllocator<Pair, 1>;
98     using Inner   = CountingAllocator<Pair, 2>;
99     using SA      = std::scoped_allocator_adaptor<Outer, Inner>;
100     using SAInner = std::scoped_allocator_adaptor<Inner>;
101     static_assert(!std::uses_allocator<T, Outer>::value, "");
102     static_assert(std::uses_allocator<T, Inner>::value, "");
103     Pair* ptr = (Pair*)std::malloc(sizeof(Pair));
104     assert(ptr);
105     Outer O(POuter);
106     Inner I(PInner);
107     SA A(O, I);
108     A.construct(ptr);
109     assert(checkConstruct<>(ptr->first, UA_AllocArg, I));
110     assert(checkConstruct<>(ptr->second, UA_AllocLast));
111 #if TEST_STD_VER >= 20
112     assert((POuter.checkConstruct<std::piecewise_construct_t&&,
113                                   std::tuple<std::allocator_arg_t, const SAInner&>&&,
114                                   std::tuple<const SAInner&>&& >(O, ptr)));
115 #else
116     assert((POuter.checkConstruct<std::piecewise_construct_t const&,
117                                   std::tuple<std::allocator_arg_t, SAInner&>&&,
118                                   std::tuple<SAInner&>&& >(O, ptr)));
119 #endif
120     A.destroy(ptr);
121     std::free(ptr);
122   }
123   PInner.reset();
124   POuter.reset();
125   {
126     using T       = UsesAllocatorV3<VoidAlloc2, 0>;
127     using U       = NotUsesAllocator<VoidAlloc2, 0>;
128     using Pair    = std::pair<T, U>;
129     using Outer   = CountingAllocator<Pair, 1>;
130     using Inner   = CountingAllocator<Pair, 2>;
131     using SA      = std::scoped_allocator_adaptor<Outer, Inner>;
132     using SAInner = std::scoped_allocator_adaptor<Inner>;
133     static_assert(!std::uses_allocator<T, Outer>::value, "");
134     static_assert(std::uses_allocator<T, Inner>::value, "");
135     Pair* ptr = (Pair*)std::malloc(sizeof(Pair));
136     assert(ptr);
137     Outer O(POuter);
138     Inner I(PInner);
139     SA A(O, I);
140     A.construct(ptr);
141     assert(checkConstruct<>(ptr->first, UA_AllocArg, I));
142     assert(checkConstruct<>(ptr->second, UA_None));
143 #if TEST_STD_VER >= 20
144     assert((POuter.checkConstruct<std::piecewise_construct_t&&,
145                                   std::tuple<std::allocator_arg_t, const SAInner&>&&,
146                                   std::tuple<>&& >(O, ptr)));
147 #else
148     assert((POuter.checkConstruct<std::piecewise_construct_t const&,
149                                   std::tuple<std::allocator_arg_t, SAInner&>&&,
150                                   std::tuple<>&& >(O, ptr)));
151 #endif
152     A.destroy(ptr);
153     std::free(ptr);
154   }
155 }
main(int,char **)156 int main(int, char**) {
157   test_no_inner_alloc();
158   test_with_inner_alloc();
159 
160   return 0;
161 }
162