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 // UNSUPPORTED: c++98, c++03, c++11 11 12 // <experimental/tuple> 13 14 // template <class F, class T> constexpr decltype(auto) apply(F &&, T &&) 15 16 // Stress testing large arities with tuple and array. 17 18 #include <experimental/tuple> 19 #include <array> 20 #include <utility> 21 #include <cassert> 22 23 //////////////////////////////////////////////////////////////////////////////// 24 template <class T, std::size_t Dummy = 0> 25 struct always_imp 26 { 27 typedef T type; 28 }; 29 30 template <class T, std::size_t Dummy = 0> 31 using always_t = typename always_imp<T, Dummy>::type; 32 33 //////////////////////////////////////////////////////////////////////////////// 34 template <class Tuple, class Idx> 35 struct make_function; 36 37 template <class Tp, std::size_t ...Idx> 38 struct make_function<Tp, std::integer_sequence<std::size_t, Idx...>> 39 { 40 using type = bool (*)(always_t<Tp, Idx>...); 41 }; 42 43 template <class Tp, std::size_t Size> 44 using make_function_t = typename make_function<Tp, std::make_index_sequence<Size>>::type; 45 46 //////////////////////////////////////////////////////////////////////////////// 47 template <class Tp, class Idx> 48 struct make_tuple_imp; 49 50 //////////////////////////////////////////////////////////////////////////////// 51 template <class Tp, std::size_t ...Idx> 52 struct make_tuple_imp<Tp, std::integer_sequence<std::size_t, Idx...>> 53 { 54 using type = std::tuple<always_t<Tp, Idx>...>; 55 }; 56 57 template <class Tp, std::size_t Size> 58 using make_tuple_t = typename make_tuple_imp<Tp, std::make_index_sequence<Size>>::type; 59 60 template <class ...Types> 61 bool test_apply_fn(Types...) { return true; } 62 63 namespace ex = std::experimental; 64 65 template <std::size_t Size> 66 void test_all() 67 { 68 69 using A = std::array<int, Size>; 70 using ConstA = std::array<int const, Size>; 71 72 using Tuple = make_tuple_t<int, Size>; 73 using CTuple = make_tuple_t<const int, Size>; 74 75 using ValFn = make_function_t<int, Size>; 76 ValFn val_fn = &test_apply_fn; 77 78 using RefFn = make_function_t<int &, Size>; 79 RefFn ref_fn = &test_apply_fn; 80 81 using CRefFn = make_function_t<int const &, Size>; 82 CRefFn cref_fn = &test_apply_fn; 83 84 using RRefFn = make_function_t<int &&, Size>; 85 RRefFn rref_fn = &test_apply_fn; 86 87 { 88 A a{}; 89 assert(ex::apply(val_fn, a)); 90 assert(ex::apply(ref_fn, a)); 91 assert(ex::apply(cref_fn, a)); 92 assert(ex::apply(rref_fn, std::move(a))); 93 } 94 { 95 ConstA a{}; 96 assert(ex::apply(val_fn, a)); 97 assert(ex::apply(cref_fn, a)); 98 } 99 { 100 Tuple a{}; 101 assert(ex::apply(val_fn, a)); 102 assert(ex::apply(ref_fn, a)); 103 assert(ex::apply(cref_fn, a)); 104 assert(ex::apply(rref_fn, std::move(a))); 105 } 106 { 107 CTuple a{}; 108 assert(ex::apply(val_fn, a)); 109 assert(ex::apply(cref_fn, a)); 110 } 111 112 } 113 114 115 template <std::size_t Size> 116 void test_one() 117 { 118 using A = std::array<int, Size>; 119 using Tuple = make_tuple_t<int, Size>; 120 121 using ValFn = make_function_t<int, Size>; 122 ValFn val_fn = &test_apply_fn; 123 124 { 125 A a{}; 126 assert(ex::apply(val_fn, a)); 127 } 128 { 129 Tuple a{}; 130 assert(ex::apply(val_fn, a)); 131 } 132 } 133 134 int main() 135 { 136 // Instantiate with 1-5 arguments. 137 test_all<1>(); 138 test_all<2>(); 139 test_all<3>(); 140 test_all<4>(); 141 test_all<5>(); 142 143 // Stress test with 128. 144 test_one<128>(); 145 //test_one<256>(); 146 } 147