apply_large_arity.pass.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. // UNSUPPORTED: c++98, c++03, c++11, c++14
  9. // <tuple>
  10. // template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
  11. // Stress testing large arities with tuple and array.
  12. #include <tuple>
  13. #include <array>
  14. #include <utility>
  15. #include <cassert>
  16. #include "test_macros.h"
  17. ////////////////////////////////////////////////////////////////////////////////
  18. template <class T, std::size_t Dummy = 0>
  19. struct always_imp
  20. {
  21. typedef T type;
  22. };
  23. template <class T, std::size_t Dummy = 0>
  24. using always_t = typename always_imp<T, Dummy>::type;
  25. ////////////////////////////////////////////////////////////////////////////////
  26. template <class Tuple, class Idx>
  27. struct make_function;
  28. template <class Tp, std::size_t ...Idx>
  29. struct make_function<Tp, std::integer_sequence<std::size_t, Idx...>>
  30. {
  31. using type = bool (*)(always_t<Tp, Idx>...);
  32. };
  33. template <class Tp, std::size_t Size>
  34. using make_function_t = typename make_function<Tp, std::make_index_sequence<Size>>::type;
  35. ////////////////////////////////////////////////////////////////////////////////
  36. template <class Tp, class Idx>
  37. struct make_tuple_imp;
  38. ////////////////////////////////////////////////////////////////////////////////
  39. template <class Tp, std::size_t ...Idx>
  40. struct make_tuple_imp<Tp, std::integer_sequence<std::size_t, Idx...>>
  41. {
  42. using type = std::tuple<always_t<Tp, Idx>...>;
  43. };
  44. template <class Tp, std::size_t Size>
  45. using make_tuple_t = typename make_tuple_imp<Tp, std::make_index_sequence<Size>>::type;
  46. template <class ...Types>
  47. bool test_apply_fn(Types...) { return true; }
  48. template <std::size_t Size>
  49. void test_all()
  50. {
  51. using A = std::array<int, Size>;
  52. using ConstA = std::array<int const, Size>;
  53. using Tuple = make_tuple_t<int, Size>;
  54. using CTuple = make_tuple_t<const int, Size>;
  55. using ValFn = make_function_t<int, Size>;
  56. ValFn val_fn = &test_apply_fn;
  57. using RefFn = make_function_t<int &, Size>;
  58. RefFn ref_fn = &test_apply_fn;
  59. using CRefFn = make_function_t<int const &, Size>;
  60. CRefFn cref_fn = &test_apply_fn;
  61. using RRefFn = make_function_t<int &&, Size>;
  62. RRefFn rref_fn = &test_apply_fn;
  63. {
  64. A a{};
  65. assert(std::apply(val_fn, a));
  66. assert(std::apply(ref_fn, a));
  67. assert(std::apply(cref_fn, a));
  68. assert(std::apply(rref_fn, std::move(a)));
  69. }
  70. {
  71. ConstA a{};
  72. assert(std::apply(val_fn, a));
  73. assert(std::apply(cref_fn, a));
  74. }
  75. {
  76. Tuple a{};
  77. assert(std::apply(val_fn, a));
  78. assert(std::apply(ref_fn, a));
  79. assert(std::apply(cref_fn, a));
  80. assert(std::apply(rref_fn, std::move(a)));
  81. }
  82. {
  83. CTuple a{};
  84. assert(std::apply(val_fn, a));
  85. assert(std::apply(cref_fn, a));
  86. }
  87. }
  88. template <std::size_t Size>
  89. void test_one()
  90. {
  91. using A = std::array<int, Size>;
  92. using Tuple = make_tuple_t<int, Size>;
  93. using ValFn = make_function_t<int, Size>;
  94. ValFn val_fn = &test_apply_fn;
  95. {
  96. A a{};
  97. assert(std::apply(val_fn, a));
  98. }
  99. {
  100. Tuple a{};
  101. assert(std::apply(val_fn, a));
  102. }
  103. }
  104. int main(int, char**)
  105. {
  106. // Instantiate with 1-5 arguments.
  107. test_all<1>();
  108. test_all<2>();
  109. test_all<3>();
  110. test_all<4>();
  111. test_all<5>();
  112. // Stress test with 256
  113. test_one<256>();
  114. return 0;
  115. }