]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_types.pass.cpp
Vendor import of libc++ trunk r300422:
[FreeBSD/FreeBSD.git] / test / std / experimental / memory / memory.polymorphic.allocator.class / memory.polymorphic.allocator.mem / construct_types.pass.cpp
1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // REQUIRES: c++experimental
11 // UNSUPPORTED: c++98, c++03
12
13 // <experimental/memory_resource>
14
15 // template <class T> class polymorphic_allocator
16
17 // template <class U, class ...Args>
18 // void polymorphic_allocator<T>::construct(U *, Args &&...)
19
20 #include <experimental/memory_resource>
21 #include <type_traits>
22 #include <cassert>
23 #include <cstdlib>
24
25 #include "test_macros.h"
26 #include "test_memory_resource.hpp"
27 #include "uses_alloc_types.hpp"
28 #include "controlled_allocators.hpp"
29 #include "test_allocator.h"
30
31 namespace ex = std::experimental::pmr;
32
33 template <class T>
34 struct PMATest {
35     TestResource R;
36     ex::polymorphic_allocator<T> A;
37     T* ptr;
38     bool constructed;
39
40     PMATest() : A(&R), ptr(A.allocate(1)), constructed(false) {}
41
42     template <class ...Args>
43     void construct(Args&&... args) {
44         A.construct(ptr, std::forward<Args>(args)...);
45         constructed = true;
46     }
47
48     ~PMATest() {
49         if (constructed) A.destroy(ptr);
50         A.deallocate(ptr, 1);
51     }
52 };
53
54 template <class T, class ...Args>
55 bool doTest(UsesAllocatorType UAExpect, Args&&... args)
56 {
57     PMATest<T> TH;
58     // UNDER TEST //
59     TH.construct(std::forward<Args>(args)...);
60     return checkConstruct<Args&&...>(*TH.ptr, UAExpect, &TH.R);
61     // ------- //
62 }
63
64
65 template <class T, class ...Args>
66 bool doTestUsesAllocV0(Args&&... args)
67 {
68     PMATest<T> TH;
69     // UNDER TEST //
70     TH.construct(std::forward<Args>(args)...);
71     return checkConstruct<Args&&...>(*TH.ptr, UA_None);
72     // -------- //
73 }
74
75
76 template <class T, class EAlloc, class ...Args>
77 bool doTestUsesAllocV1(EAlloc const& ealloc, Args&&... args)
78 {
79     PMATest<T> TH;
80     // UNDER TEST //
81     TH.construct(std::allocator_arg, ealloc, std::forward<Args>(args)...);
82     return checkConstruct<Args&&...>(*TH.ptr, UA_AllocArg, ealloc);
83     // -------- //
84 }
85
86 template <class T, class EAlloc, class ...Args>
87 bool doTestUsesAllocV2(EAlloc const& ealloc, Args&&... args)
88 {
89     PMATest<T> TH;
90     // UNDER TEST //
91     TH.construct(std::forward<Args>(args)..., ealloc);
92     return checkConstruct<Args&&...>(*TH.ptr, UA_AllocLast, ealloc);
93     // -------- //
94 }
95
96 template <class Alloc, class ...Args>
97 void test_pmr_uses_alloc(Args&&... args)
98 {
99     TestResource R(12435);
100     ex::memory_resource* M = &R;
101     {
102         // NotUsesAllocator provides valid signatures for each uses-allocator
103         // construction but does not supply the required allocator_type typedef.
104         // Test that we can call these constructors manually without
105         // polymorphic_allocator interfering.
106         using T = NotUsesAllocator<Alloc, sizeof...(Args)>;
107         assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
108         assert((doTestUsesAllocV1<T>(M, std::forward<Args>(args)...)));
109         assert((doTestUsesAllocV2<T>(M, std::forward<Args>(args)...)));
110     }
111     {
112         // Test T(std::allocator_arg_t, Alloc const&, Args...) construction
113         using T = UsesAllocatorV1<Alloc, sizeof...(Args)>;
114         assert((doTest<T>(UA_AllocArg, std::forward<Args>(args)...)));
115     }
116     {
117         // Test T(Args..., Alloc const&) construction
118         using T = UsesAllocatorV2<Alloc, sizeof...(Args)>;
119         assert((doTest<T>(UA_AllocLast, std::forward<Args>(args)...)));
120     }
121     {
122         // Test that T(std::allocator_arg_t, Alloc const&, Args...) construction
123         // is preferred when T(Args..., Alloc const&) is also available.
124         using T = UsesAllocatorV3<Alloc, sizeof...(Args)>;
125         assert((doTest<T>(UA_AllocArg, std::forward<Args>(args)...)));
126     }
127 }
128
129 // Test that polymorphic_allocator does not prevent us from manually
130 // doing non-pmr uses-allocator construction.
131 template <class Alloc, class AllocObj, class ...Args>
132 void test_non_pmr_uses_alloc(AllocObj const& A, Args&&... args)
133 {
134     {
135         using T = NotUsesAllocator<Alloc, sizeof...(Args)>;
136         assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
137         assert((doTestUsesAllocV1<T>(A, std::forward<Args>(args)...)));
138         assert((doTestUsesAllocV2<T>(A, std::forward<Args>(args)...)));
139     }
140     {
141         using T = UsesAllocatorV1<Alloc, sizeof...(Args)>;
142         assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
143         assert((doTestUsesAllocV1<T>(A, std::forward<Args>(args)...)));
144     }
145     {
146         using T = UsesAllocatorV2<Alloc, sizeof...(Args)>;
147         assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
148         assert((doTestUsesAllocV2<T>(A, std::forward<Args>(args)...)));
149     }
150     {
151         using T = UsesAllocatorV3<Alloc, sizeof...(Args)>;
152         assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
153         assert((doTestUsesAllocV1<T>(A, std::forward<Args>(args)...)));
154         assert((doTestUsesAllocV2<T>(A, std::forward<Args>(args)...)));
155     }
156 }
157
158 int main()
159 {
160     using ET = std::experimental::erased_type;
161     using PMR = ex::memory_resource*;
162     using PMA = ex::polymorphic_allocator<void>;
163     using STDA = std::allocator<char>;
164     using TESTA = test_allocator<char>;
165
166     int value = 42;
167     const int cvalue = 43;
168     {
169         test_pmr_uses_alloc<ET>();
170         test_pmr_uses_alloc<PMR>();
171         test_pmr_uses_alloc<PMA>();
172         test_pmr_uses_alloc<ET>(value);
173         test_pmr_uses_alloc<PMR>(value);
174         test_pmr_uses_alloc<PMA>(value);
175         test_pmr_uses_alloc<ET>(cvalue);
176         test_pmr_uses_alloc<PMR>(cvalue);
177         test_pmr_uses_alloc<PMA>(cvalue);
178         test_pmr_uses_alloc<ET>(cvalue, std::move(value));
179         test_pmr_uses_alloc<PMR>(cvalue, std::move(value));
180         test_pmr_uses_alloc<PMA>(cvalue, std::move(value));
181     }
182     {
183         STDA std_alloc;
184         TESTA test_alloc(42);
185         test_non_pmr_uses_alloc<STDA>(std_alloc);
186         test_non_pmr_uses_alloc<TESTA>(test_alloc);
187         test_non_pmr_uses_alloc<STDA>(std_alloc, value);
188         test_non_pmr_uses_alloc<TESTA>(test_alloc, value);
189         test_non_pmr_uses_alloc<STDA>(std_alloc, cvalue);
190         test_non_pmr_uses_alloc<TESTA>(test_alloc, cvalue);
191         test_non_pmr_uses_alloc<STDA>(std_alloc, cvalue, std::move(value));
192         test_non_pmr_uses_alloc<TESTA>(test_alloc, cvalue, std::move(value));
193     }
194 }