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 // <tuple> 10 11 // template <class... Types> class tuple; 12 13 // template <class Alloc, class... UTypes> 14 // tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&); 15 16 // UNSUPPORTED: c++03 17 18 #include <tuple> 19 #include <string> 20 #include <memory> 21 #include <cassert> 22 23 #include "test_macros.h" 24 #include "allocators.h" 25 #include "test_allocator.h" 26 #include "../alloc_first.h" 27 #include "../alloc_last.h" 28 29 struct B 30 { 31 int id_; 32 33 explicit B(int i) : id_(i) {} 34 35 virtual ~B() {} 36 }; 37 38 struct D 39 : B 40 { 41 explicit D(int i) : B(i) {} 42 }; 43 44 struct Explicit { 45 int value; 46 explicit Explicit(int x) : value(x) {} 47 }; 48 49 struct Implicit { 50 int value; 51 Implicit(int x) : value(x) {} 52 }; 53 54 #if _LIBCPP_STD_VER > 17 55 constexpr bool alloc_move_constructor_is_constexpr() { 56 std::tuple<int> t1 = 1; 57 std::tuple<int> t2 = {std::allocator_arg, test_allocator<int>{}, std::move(t1)}; 58 assert(std::get<0>(t2) == 1); 59 return true; 60 } 61 #endif 62 63 int main(int, char**) 64 { 65 { 66 typedef std::tuple<int> T0; 67 typedef std::tuple<alloc_first> T1; 68 T0 t0(2); 69 alloc_first::allocator_constructed = false; 70 T1 t1(std::allocator_arg, A1<int>(5), std::move(t0)); 71 assert(alloc_first::allocator_constructed); 72 assert(std::get<0>(t1) == 2); 73 } 74 { 75 typedef std::tuple<std::unique_ptr<D>> T0; 76 typedef std::tuple<std::unique_ptr<B>> T1; 77 T0 t0(std::unique_ptr<D>(new D(3))); 78 T1 t1(std::allocator_arg, A1<int>(5), std::move(t0)); 79 assert(std::get<0>(t1)->id_ == 3); 80 } 81 { 82 typedef std::tuple<int, std::unique_ptr<D>> T0; 83 typedef std::tuple<alloc_first, std::unique_ptr<B>> T1; 84 T0 t0(2, std::unique_ptr<D>(new D(3))); 85 alloc_first::allocator_constructed = false; 86 T1 t1(std::allocator_arg, A1<int>(5), std::move(t0)); 87 assert(alloc_first::allocator_constructed); 88 assert(std::get<0>(t1) == 2); 89 assert(std::get<1>(t1)->id_ == 3); 90 } 91 { 92 typedef std::tuple<int, int, std::unique_ptr<D>> T0; 93 typedef std::tuple<alloc_last, alloc_first, std::unique_ptr<B>> T1; 94 T0 t0(1, 2, std::unique_ptr<D>(new D(3))); 95 alloc_first::allocator_constructed = false; 96 alloc_last::allocator_constructed = false; 97 T1 t1(std::allocator_arg, A1<int>(5), std::move(t0)); 98 assert(alloc_first::allocator_constructed); 99 assert(alloc_last::allocator_constructed); 100 assert(std::get<0>(t1) == 1); 101 assert(std::get<1>(t1) == 2); 102 assert(std::get<2>(t1)->id_ == 3); 103 } 104 { 105 std::tuple<int> t1(42); 106 std::tuple<Explicit> t2{std::allocator_arg, std::allocator<int>{}, std::move(t1)}; 107 assert(std::get<0>(t2).value == 42); 108 } 109 { 110 std::tuple<int> t1(42); 111 std::tuple<Implicit> t2 = {std::allocator_arg, std::allocator<int>{}, std::move(t1)}; 112 assert(std::get<0>(t2).value == 42); 113 } 114 { 115 // Test that we can use a tag derived from allocator_arg_t 116 struct DerivedFromAllocatorArgT : std::allocator_arg_t { }; 117 DerivedFromAllocatorArgT derived; 118 std::tuple<long> from(3l); 119 std::tuple<long long> t0(derived, A1<int>(), std::move(from)); 120 } 121 122 #if _LIBCPP_STD_VER > 17 123 static_assert(alloc_move_constructor_is_constexpr()); 124 #endif 125 126 return 0; 127 } 128