blob: 027258ad8d1d979a8f2eb00e2ad1abe9cffba78c [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11
// <experimental/tuple>
// template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
// Stress testing large arities with tuple and array.
#include <experimental/tuple>
#include <array>
#include <utility>
#include <cassert>
////////////////////////////////////////////////////////////////////////////////
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; }
namespace ex = std::experimental;
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(ex::apply(val_fn, a));
assert(ex::apply(ref_fn, a));
assert(ex::apply(cref_fn, a));
assert(ex::apply(rref_fn, std::move(a)));
}
{
ConstA a{};
assert(ex::apply(val_fn, a));
assert(ex::apply(cref_fn, a));
}
{
Tuple a{};
assert(ex::apply(val_fn, a));
assert(ex::apply(ref_fn, a));
assert(ex::apply(cref_fn, a));
assert(ex::apply(rref_fn, std::move(a)));
}
{
CTuple a{};
assert(ex::apply(val_fn, a));
assert(ex::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(ex::apply(val_fn, a));
}
{
Tuple a{};
assert(ex::apply(val_fn, a));
}
}
int main()
{
// Instantiate with 1-5 arguments.
test_all<1>();
test_all<2>();
test_all<3>();
test_all<4>();
test_all<5>();
// Stress test with 128.
test_one<128>();
//test_one<256>();
}