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 // UNSUPPORTED: c++98, c++03, c++11, c++14 10 11 // <tuple> 12 13 // template <class F, class T> constexpr decltype(auto) apply(F &&, T &&) 14 15 // Stress testing large arities with tuple and array. 16 17 #include <tuple> 18 #include <array> 19 #include <utility> 20 #include <cassert> 21 22 #include "test_macros.h" 23 24 //////////////////////////////////////////////////////////////////////////////// 25 template <class T, std::size_t Dummy = 0> 26 struct always_imp 27 { 28 typedef T type; 29 }; 30 31 template <class T, std::size_t Dummy = 0> 32 using always_t = typename always_imp<T, Dummy>::type; 33 34 //////////////////////////////////////////////////////////////////////////////// 35 template <class Tuple, class Idx> 36 struct make_function; 37 38 template <class Tp, std::size_t ...Idx> 39 struct make_function<Tp, std::integer_sequence<std::size_t, Idx...>> 40 { 41 using type = bool (*)(always_t<Tp, Idx>...); 42 }; 43 44 template <class Tp, std::size_t Size> 45 using make_function_t = typename make_function<Tp, std::make_index_sequence<Size>>::type; 46 47 //////////////////////////////////////////////////////////////////////////////// 48 template <class Tp, class Idx> 49 struct make_tuple_imp; 50 51 //////////////////////////////////////////////////////////////////////////////// 52 template <class Tp, std::size_t ...Idx> 53 struct make_tuple_imp<Tp, std::integer_sequence<std::size_t, Idx...>> 54 { 55 using type = std::tuple<always_t<Tp, Idx>...>; 56 }; 57 58 template <class Tp, std::size_t Size> 59 using make_tuple_t = typename make_tuple_imp<Tp, std::make_index_sequence<Size>>::type; 60 61 template <class ...Types> 62 bool test_apply_fn(Types...) { return true; } 63 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(std::apply(val_fn, a)); 90 assert(std::apply(ref_fn, a)); 91 assert(std::apply(cref_fn, a)); 92 assert(std::apply(rref_fn, std::move(a))); 93 } 94 { 95 ConstA a{}; 96 assert(std::apply(val_fn, a)); 97 assert(std::apply(cref_fn, a)); 98 } 99 { 100 Tuple a{}; 101 assert(std::apply(val_fn, a)); 102 assert(std::apply(ref_fn, a)); 103 assert(std::apply(cref_fn, a)); 104 assert(std::apply(rref_fn, std::move(a))); 105 } 106 { 107 CTuple a{}; 108 assert(std::apply(val_fn, a)); 109 assert(std::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(std::apply(val_fn, a)); 127 } 128 { 129 Tuple a{}; 130 assert(std::apply(val_fn, a)); 131 } 132 } 133 134 int main(int, char**) 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 256 144 test_one<256>(); 145 146 return 0; 147 } 148