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 P1, class P2, class U1, class U2> 18 // void polymorphic_allocator<T>::construct(pair<P1, P2>*, pair<U1, U2> &&) 19 20 #include <experimental/memory_resource> 21 #include <type_traits> 22 #include <utility> 23 #include <tuple> 24 #include <cassert> 25 #include <cstdlib> 26 27 #include "test_macros.h" 28 #include "test_memory_resource.hpp" 29 #include "uses_alloc_types.hpp" 30 #include "controlled_allocators.hpp" 31 #include "test_allocator.h" 32 33 namespace ex = std::experimental::pmr; 34 35 36 37 template <class UA1, class UA2, class TT, class UU> 38 bool doTest(UsesAllocatorType TExpect, UsesAllocatorType UExpect, 39 std::pair<TT, UU>&& p) 40 { 41 using P = std::pair<UA1, UA2>; 42 TestResource R; 43 ex::memory_resource * M = &R; 44 ex::polymorphic_allocator<P> A(M); 45 P * ptr = A.allocate(2); 46 P * ptr2 = ptr + 1; 47 48 // UNDER TEST // 49 A.construct(ptr, std::move(p)); 50 51 A.construct(ptr2, std::piecewise_construct, 52 std::forward_as_tuple(std::forward<TT>(p.first)), 53 std::forward_as_tuple(std::forward<UU>(p.second))); 54 // ------- // 55 56 bool tres = checkConstruct<TT&&>(ptr->first, TExpect, M) && 57 checkConstructionEquiv(ptr->first, ptr2->first); 58 59 bool ures = checkConstruct<UU&&>(ptr->second, UExpect, M) && 60 checkConstructionEquiv(ptr->second, ptr2->second); 61 62 A.destroy(ptr); 63 A.destroy(ptr2); 64 A.deallocate(ptr, 2); 65 return tres && ures; 66 } 67 68 template <class Alloc, class TT, class UU> 69 void test_pmr_uses_allocator(std::pair<TT, UU>&& p) 70 { 71 { 72 using T = NotUsesAllocator<Alloc, 1>; 73 using U = NotUsesAllocator<Alloc, 1>; 74 assert((doTest<T, U>(UA_None, UA_None, std::move(p)))); 75 } 76 { 77 using T = UsesAllocatorV1<Alloc, 1>; 78 using U = UsesAllocatorV2<Alloc, 1>; 79 assert((doTest<T, U>(UA_AllocArg, UA_AllocLast, std::move(p)))); 80 } 81 { 82 using T = UsesAllocatorV2<Alloc, 1>; 83 using U = UsesAllocatorV3<Alloc, 1>; 84 assert((doTest<T, U>(UA_AllocLast, UA_AllocArg, std::move(p)))); 85 } 86 { 87 using T = UsesAllocatorV3<Alloc, 1>; 88 using U = NotUsesAllocator<Alloc, 1>; 89 assert((doTest<T, U>(UA_AllocArg, UA_None, std::move(p)))); 90 } 91 } 92 93 template <class Alloc, class TT, class UU> 94 void test_pmr_not_uses_allocator(std::pair<TT, UU>&& p) 95 { 96 { 97 using T = NotUsesAllocator<Alloc, 1>; 98 using U = NotUsesAllocator<Alloc, 1>; 99 assert((doTest<T, U>(UA_None, UA_None, std::move(p)))); 100 } 101 { 102 using T = UsesAllocatorV1<Alloc, 1>; 103 using U = UsesAllocatorV2<Alloc, 1>; 104 assert((doTest<T, U>(UA_None, UA_None, std::move(p)))); 105 } 106 { 107 using T = UsesAllocatorV2<Alloc, 1>; 108 using U = UsesAllocatorV3<Alloc, 1>; 109 assert((doTest<T, U>(UA_None, UA_None, std::move(p)))); 110 } 111 { 112 using T = UsesAllocatorV3<Alloc, 1>; 113 using U = NotUsesAllocator<Alloc, 1>; 114 assert((doTest<T, U>(UA_None, UA_None, std::move(p)))); 115 } 116 } 117 118 int main() 119 { 120 using ERT = std::experimental::erased_type; 121 using PMR = ex::memory_resource*; 122 using PMA = ex::polymorphic_allocator<char>; 123 { 124 int x = 42; 125 int y = 42; 126 std::pair<int&, int&&> p(x, std::move(y)); 127 test_pmr_uses_allocator<ERT>(std::move(p)); 128 test_pmr_not_uses_allocator<PMR>(std::move(p)); 129 test_pmr_uses_allocator<PMA>(std::move(p)); 130 } 131 { 132 int x = 42; 133 int y = 42; 134 std::pair<int&&, int&> p(std::move(x), y); 135 test_pmr_uses_allocator<ERT>(std::move(p)); 136 test_pmr_not_uses_allocator<PMR>(std::move(p)); 137 test_pmr_uses_allocator<PMA>(std::move(p)); 138 } 139 } 140