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