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 
30 
test_no_inner_alloc()31 void test_no_inner_alloc()
32 {
33     using VoidAlloc = CountingAllocator<void>;
34     AllocController P;
35     {
36         using T = UsesAllocatorV1<VoidAlloc, 0>;
37         using U = UsesAllocatorV2<VoidAlloc, 0>;
38         using Pair = std::pair<T, U>;
39         using Alloc = CountingAllocator<Pair>;
40         using SA = std::scoped_allocator_adaptor<Alloc>;
41         static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, "");
42         Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
43         assert(ptr);
44         Alloc CA(P);
45         SA A(CA);
46         A.construct(ptr);
47         assert(checkConstruct<>(ptr->first, UA_AllocArg, CA));
48         assert(checkConstruct<>(ptr->second, UA_AllocLast, CA));
49         assert((P.checkConstruct<std::piecewise_construct_t const&,
50                                  std::tuple<std::allocator_arg_t, SA&>&&,
51                                  std::tuple<SA&>&&
52               >(CA, ptr)));
53         A.destroy(ptr);
54         std::free(ptr);
55 
56     }
57     P.reset();
58     {
59         using T = UsesAllocatorV3<VoidAlloc, 0>;
60         using U = NotUsesAllocator<VoidAlloc, 0>;
61         using Pair = std::pair<T, U>;
62         using Alloc = CountingAllocator<Pair>;
63         using SA = std::scoped_allocator_adaptor<Alloc>;
64         static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, "");
65         Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
66         assert(ptr);
67         Alloc CA(P);
68         SA A(CA);
69         A.construct(ptr);
70         assert(checkConstruct<>(ptr->first, UA_AllocArg, CA));
71         assert(checkConstruct<>(ptr->second, UA_None));
72         assert((P.checkConstruct<std::piecewise_construct_t const&,
73                                  std::tuple<std::allocator_arg_t, SA&>&&,
74                                  std::tuple<>&&
75                    >(CA, ptr)));
76         A.destroy(ptr);
77         std::free(ptr);
78     }
79 }
80 
test_with_inner_alloc()81 void test_with_inner_alloc()
82 {
83     using VoidAlloc2 = CountingAllocator<void, 2>;
84 
85     AllocController POuter;
86     AllocController PInner;
87     {
88         using T = UsesAllocatorV1<VoidAlloc2, 0>;
89         using U = UsesAllocatorV2<VoidAlloc2, 0>;
90         using Pair = std::pair<T, U>;
91         using Outer = CountingAllocator<Pair, 1>;
92         using Inner = CountingAllocator<Pair, 2>;
93         using SA = std::scoped_allocator_adaptor<Outer, Inner>;
94         using SAInner = std::scoped_allocator_adaptor<Inner>;
95         static_assert(!std::uses_allocator<T, Outer>::value, "");
96         static_assert(std::uses_allocator<T, Inner>::value, "");
97         Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
98         assert(ptr);
99         Outer O(POuter);
100         Inner I(PInner);
101         SA A(O, I);
102         A.construct(ptr);
103         assert(checkConstruct<>(ptr->first, UA_AllocArg, I));
104         assert(checkConstruct<>(ptr->second, UA_AllocLast));
105         assert((POuter.checkConstruct<std::piecewise_construct_t const&,
106                                  std::tuple<std::allocator_arg_t, SAInner&>&&,
107                                  std::tuple<SAInner&>&&
108               >(O, ptr)));
109         A.destroy(ptr);
110         std::free(ptr);
111     }
112     PInner.reset();
113     POuter.reset();
114     {
115         using T = UsesAllocatorV3<VoidAlloc2, 0>;
116         using U = NotUsesAllocator<VoidAlloc2, 0>;
117         using Pair = std::pair<T, U>;
118         using Outer = CountingAllocator<Pair, 1>;
119         using Inner = CountingAllocator<Pair, 2>;
120         using SA = std::scoped_allocator_adaptor<Outer, Inner>;
121         using SAInner = std::scoped_allocator_adaptor<Inner>;
122         static_assert(!std::uses_allocator<T, Outer>::value, "");
123         static_assert(std::uses_allocator<T, Inner>::value, "");
124         Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
125         assert(ptr);
126         Outer O(POuter);
127         Inner I(PInner);
128         SA A(O, I);
129         A.construct(ptr);
130         assert(checkConstruct<>(ptr->first, UA_AllocArg, I));
131         assert(checkConstruct<>(ptr->second, UA_None));
132         assert((POuter.checkConstruct<std::piecewise_construct_t const&,
133                                  std::tuple<std::allocator_arg_t, SAInner&>&&,
134                                  std::tuple<>&&
135               >(O, ptr)));
136         A.destroy(ptr);
137         std::free(ptr);
138     }
139 }
main(int,char **)140 int main(int, char**) {
141     test_no_inner_alloc();
142     test_with_inner_alloc();
143 
144   return 0;
145 }
146