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// <tuple> 11 12// template <class... Types> class tuple; 13 14// template <class Alloc, class... UTypes> 15// tuple(allocator_arg_t, const Alloc& a, UTypes&&...); 16 17// UNSUPPORTED: c++98, c++03 18 19#include <tuple> 20#include <cassert> 21 22#include "MoveOnly.h" 23#include "allocators.h" 24#include "../alloc_first.h" 25#include "../alloc_last.h" 26 27template <class T = void> 28struct DefaultCtorBlowsUp { 29 constexpr DefaultCtorBlowsUp() { 30 static_assert(!std::is_same<T, T>::value, "Default Ctor instantiated"); 31 } 32 33 explicit constexpr DefaultCtorBlowsUp(int x) : value(x) {} 34 35 int value; 36}; 37 38 39struct DerivedFromAllocArgT : std::allocator_arg_t {}; 40 41 42// Make sure the _Up... constructor SFINAEs out when the number of initializers 43// is less that the number of elements in the tuple. Previously libc++ would 44// offer these constructers as an extension but they broke conforming code. 45void test_uses_allocator_sfinae_evaluation() 46{ 47 using BadDefault = DefaultCtorBlowsUp<>; 48 { 49 typedef std::tuple<MoveOnly, MoveOnly, BadDefault> Tuple; 50 51 static_assert(!std::is_constructible< 52 Tuple, 53 std::allocator_arg_t, A1<int>, MoveOnly 54 >::value, ""); 55 56 static_assert(std::is_constructible< 57 Tuple, 58 std::allocator_arg_t, A1<int>, MoveOnly, MoveOnly, BadDefault 59 >::value, ""); 60 } 61 { 62 typedef std::tuple<MoveOnly, MoveOnly, BadDefault, BadDefault> Tuple; 63 64 static_assert(!std::is_constructible< 65 Tuple, 66 std::allocator_arg_t, A1<int>, MoveOnly, MoveOnly 67 >::value, ""); 68 69 static_assert(std::is_constructible< 70 Tuple, 71 std::allocator_arg_t, A1<int>, MoveOnly, MoveOnly, BadDefault, BadDefault 72 >::value, ""); 73 } 74} 75 76struct Explicit { 77 int value; 78 explicit Explicit(int x) : value(x) {} 79}; 80 81int main() 82{ 83 { 84 std::tuple<Explicit> t{std::allocator_arg, std::allocator<void>{}, 42}; 85 assert(std::get<0>(t).value == 42); 86 } 87 { 88 std::tuple<MoveOnly> t(std::allocator_arg, A1<int>(), MoveOnly(0)); 89 assert(std::get<0>(t) == 0); 90 } 91 { 92 using T = DefaultCtorBlowsUp<>; 93 std::tuple<T> t(std::allocator_arg, A1<int>(), T(42)); 94 assert(std::get<0>(t).value == 42); 95 } 96 { 97 std::tuple<MoveOnly, MoveOnly> t(std::allocator_arg, A1<int>(), 98 MoveOnly(0), MoveOnly(1)); 99 assert(std::get<0>(t) == 0); 100 assert(std::get<1>(t) == 1); 101 } 102 { 103 using T = DefaultCtorBlowsUp<>; 104 std::tuple<T, T> t(std::allocator_arg, A1<int>(), T(42), T(43)); 105 assert(std::get<0>(t).value == 42); 106 assert(std::get<1>(t).value == 43); 107 } 108 { 109 std::tuple<MoveOnly, MoveOnly, MoveOnly> t(std::allocator_arg, A1<int>(), 110 MoveOnly(0), 111 1, 2); 112 assert(std::get<0>(t) == 0); 113 assert(std::get<1>(t) == 1); 114 assert(std::get<2>(t) == 2); 115 } 116 { 117 using T = DefaultCtorBlowsUp<>; 118 std::tuple<T, T, T> t(std::allocator_arg, A1<int>(), T(1), T(2), T(3)); 119 assert(std::get<0>(t).value == 1); 120 assert(std::get<1>(t).value == 2); 121 assert(std::get<2>(t).value == 3); 122 } 123 { 124 alloc_first::allocator_constructed = false; 125 alloc_last::allocator_constructed = false; 126 std::tuple<int, alloc_first, alloc_last> t(std::allocator_arg, 127 A1<int>(5), 1, 2, 3); 128 assert(std::get<0>(t) == 1); 129 assert(alloc_first::allocator_constructed); 130 assert(std::get<1>(t) == alloc_first(2)); 131 assert(alloc_last::allocator_constructed); 132 assert(std::get<2>(t) == alloc_last(3)); 133 } 134 { 135 // Check that uses-allocator construction is still selected when 136 // given a tag type that derives from allocator_arg_t. 137 DerivedFromAllocArgT tag; 138 alloc_first::allocator_constructed = false; 139 alloc_last::allocator_constructed = false; 140 std::tuple<int, alloc_first, alloc_last> t(tag, 141 A1<int>(5), 1, 2, 3); 142 assert(std::get<0>(t) == 1); 143 assert(alloc_first::allocator_constructed); 144 assert(std::get<1>(t) == alloc_first(2)); 145 assert(alloc_last::allocator_constructed); 146 assert(std::get<2>(t) == alloc_last(3)); 147 } 148 // Stress test the SFINAE on the uses-allocator constructors and 149 // ensure that the "reduced-arity-initialization" extension is not offered 150 // for these constructors. 151 test_uses_allocator_sfinae_evaluation(); 152} 153