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, 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 ////////////////////////////////////////////////////////////////////////////////
     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 
     64 template <std::size_t Size>
     65 void 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 
    114 template <std::size_t Size>
    115 void 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 
    133 int 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