|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | // UNSUPPORTED: c++03, c++11, c++14 | 
|  |  | 
|  | // <tuple> | 
|  |  | 
|  | // template <class F, class T> constexpr decltype(auto) apply(F &&, T &&) | 
|  |  | 
|  | // Stress testing large arities with tuple and array. | 
|  |  | 
|  | #include <tuple> | 
|  | #include <array> | 
|  | #include <utility> | 
|  | #include <cassert> | 
|  |  | 
|  | #include "test_macros.h" | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | template <class T, std::size_t Dummy = 0> | 
|  | struct always_imp | 
|  | { | 
|  | typedef T type; | 
|  | }; | 
|  |  | 
|  | template <class T, std::size_t Dummy = 0> | 
|  | using always_t = typename always_imp<T, Dummy>::type; | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | template <class Tuple, class Idx> | 
|  | struct make_function; | 
|  |  | 
|  | template <class Tp, std::size_t ...Idx> | 
|  | struct make_function<Tp, std::integer_sequence<std::size_t, Idx...>> | 
|  | { | 
|  | using type = bool (*)(always_t<Tp, Idx>...); | 
|  | }; | 
|  |  | 
|  | template <class Tp, std::size_t Size> | 
|  | using make_function_t = typename make_function<Tp, std::make_index_sequence<Size>>::type; | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | template <class Tp, class Idx> | 
|  | struct make_tuple_imp; | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | template <class Tp, std::size_t ...Idx> | 
|  | struct make_tuple_imp<Tp, std::integer_sequence<std::size_t, Idx...>> | 
|  | { | 
|  | using type = std::tuple<always_t<Tp, Idx>...>; | 
|  | }; | 
|  |  | 
|  | template <class Tp, std::size_t Size> | 
|  | using make_tuple_t = typename make_tuple_imp<Tp, std::make_index_sequence<Size>>::type; | 
|  |  | 
|  | template <class ...Types> | 
|  | bool test_apply_fn(Types...) { return true; } | 
|  |  | 
|  |  | 
|  | template <std::size_t Size> | 
|  | void test_all() | 
|  | { | 
|  |  | 
|  | using A = std::array<int, Size>; | 
|  | using ConstA = std::array<int const, Size>; | 
|  |  | 
|  | using Tuple = make_tuple_t<int, Size>; | 
|  | using CTuple = make_tuple_t<const int, Size>; | 
|  |  | 
|  | using ValFn  = make_function_t<int, Size>; | 
|  | ValFn val_fn = &test_apply_fn; | 
|  |  | 
|  | using RefFn  = make_function_t<int &, Size>; | 
|  | RefFn ref_fn = &test_apply_fn; | 
|  |  | 
|  | using CRefFn = make_function_t<int const &, Size>; | 
|  | CRefFn cref_fn = &test_apply_fn; | 
|  |  | 
|  | using RRefFn = make_function_t<int &&, Size>; | 
|  | RRefFn rref_fn = &test_apply_fn; | 
|  |  | 
|  | { | 
|  | A a{}; | 
|  | assert(std::apply(val_fn, a)); | 
|  | assert(std::apply(ref_fn, a)); | 
|  | assert(std::apply(cref_fn, a)); | 
|  | assert(std::apply(rref_fn, std::move(a))); | 
|  | } | 
|  | { | 
|  | ConstA a{}; | 
|  | assert(std::apply(val_fn, a)); | 
|  | assert(std::apply(cref_fn, a)); | 
|  | } | 
|  | { | 
|  | Tuple a{}; | 
|  | assert(std::apply(val_fn, a)); | 
|  | assert(std::apply(ref_fn, a)); | 
|  | assert(std::apply(cref_fn, a)); | 
|  | assert(std::apply(rref_fn, std::move(a))); | 
|  | } | 
|  | { | 
|  | CTuple a{}; | 
|  | assert(std::apply(val_fn, a)); | 
|  | assert(std::apply(cref_fn, a)); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  |  | 
|  | template <std::size_t Size> | 
|  | void test_one() | 
|  | { | 
|  | using A = std::array<int, Size>; | 
|  | using Tuple = make_tuple_t<int, Size>; | 
|  |  | 
|  | using ValFn  = make_function_t<int, Size>; | 
|  | ValFn val_fn = &test_apply_fn; | 
|  |  | 
|  | { | 
|  | A a{}; | 
|  | assert(std::apply(val_fn, a)); | 
|  | } | 
|  | { | 
|  | Tuple a{}; | 
|  | assert(std::apply(val_fn, a)); | 
|  | } | 
|  | } | 
|  |  | 
|  | int main(int, char**) | 
|  | { | 
|  | // Instantiate with 1-5 arguments. | 
|  | test_all<1>(); | 
|  | test_all<2>(); | 
|  | test_all<3>(); | 
|  | test_all<4>(); | 
|  | test_all<5>(); | 
|  |  | 
|  | // Stress test with 256 | 
|  | test_one<256>(); | 
|  |  | 
|  | return 0; | 
|  | } |