Home | History | Annotate | Download | only in tuple.apply
      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