1 //===----------------------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // REQUIRES: c++experimental
11 // UNSUPPORTED: c++98, c++03
13 // <experimental/memory_resource>
15 // template <class T> class polymorphic_allocator
17 // template <class U, class ...Args>
18 // void polymorphic_allocator<T>::construct(U *, Args &&...)
20 #include <experimental/memory_resource>
21 #include <type_traits>
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"
31 namespace ex = std::experimental::pmr;
36 ex::polymorphic_allocator<T> A;
40 PMATest() : A(&R), ptr(A.allocate(1)), constructed(false) {}
42 template <class ...Args>
43 void construct(Args&&... args) {
44 A.construct(ptr, std::forward<Args>(args)...);
49 if (constructed) A.destroy(ptr);
54 template <class T, class ...Args>
55 bool doTest(UsesAllocatorType UAExpect, Args&&... args)
59 TH.construct(std::forward<Args>(args)...);
60 return checkConstruct<Args&&...>(*TH.ptr, UAExpect, &TH.R);
65 template <class T, class ...Args>
66 bool doTestUsesAllocV0(Args&&... args)
70 TH.construct(std::forward<Args>(args)...);
71 return checkConstruct<Args&&...>(*TH.ptr, UA_None);
76 template <class T, class EAlloc, class ...Args>
77 bool doTestUsesAllocV1(EAlloc const& ealloc, Args&&... args)
81 TH.construct(std::allocator_arg, ealloc, std::forward<Args>(args)...);
82 return checkConstruct<Args&&...>(*TH.ptr, UA_AllocArg, ealloc);
86 template <class T, class EAlloc, class ...Args>
87 bool doTestUsesAllocV2(EAlloc const& ealloc, Args&&... args)
91 TH.construct(std::forward<Args>(args)..., ealloc);
92 return checkConstruct<Args&&...>(*TH.ptr, UA_AllocLast, ealloc);
96 template <class Alloc, class ...Args>
97 void test_pmr_uses_alloc(Args&&... args)
99 TestResource R(12435);
100 ex::memory_resource* M = &R;
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)...)));
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)...)));
117 // Test T(Args..., Alloc const&) construction
118 using T = UsesAllocatorV2<Alloc, sizeof...(Args)>;
119 assert((doTest<T>(UA_AllocLast, std::forward<Args>(args)...)));
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)...)));
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)
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)...)));
141 using T = UsesAllocatorV1<Alloc, sizeof...(Args)>;
142 assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
143 assert((doTestUsesAllocV1<T>(A, std::forward<Args>(args)...)));
146 using T = UsesAllocatorV2<Alloc, sizeof...(Args)>;
147 assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
148 assert((doTestUsesAllocV2<T>(A, std::forward<Args>(args)...)));
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)...)));
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>;
167 const int cvalue = 43;
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));
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));