mgcpp
A C++ Math Library Based on CUDA
tuple_utils.hpp
Go to the documentation of this file.
1 #ifndef TUPLE_UTILS_HPP
2 #define TUPLE_UTILS_HPP
3 
4 #include <tuple>
5 #include <type_traits>
6 #include <utility>
7 
8 namespace mgcpp {
9 
10 namespace internal {
11 template <class Tuple, class F, size_t... Is>
12 constexpr decltype(auto) apply_impl(Tuple&& t,
13  F&& f,
14  std::index_sequence<Is...>) {
15  return std::make_tuple(f(std::get<Is>(std::forward<Tuple>(t)))...);
16 }
17 } // namespace internal
18 
19 template <class Tuple, class F>
20 constexpr decltype(auto) apply(Tuple&& t, F&& f) {
21  constexpr auto len = std::tuple_size<std::remove_reference_t<Tuple>>::value;
22  return internal::apply_impl(std::forward<Tuple>(t), std::forward<F>(f),
23  std::make_index_sequence<len>{});
24 }
25 
26 namespace internal {
27 template <class Tuple, class F, size_t... Is>
28 constexpr void apply_void_impl(Tuple&& t, F&& f, std::index_sequence<Is...>) {
29  (void)std::initializer_list<int>{
30  (f(std::get<Is>(std::forward<Tuple>(t))), 0)...};
31 }
32 } // namespace internal
33 
34 template <class Tuple, class F>
35 constexpr void apply_void(Tuple&& t, F&& f) {
36  constexpr auto len = std::tuple_size<std::remove_reference_t<Tuple>>::value;
37  internal::apply_void_impl(std::forward<Tuple>(t), std::forward<F>(f),
38  std::make_index_sequence<len>{});
39 }
40 
41 namespace internal {
42 template <class Tuple, size_t... Is>
43 constexpr decltype(auto) take_front_impl(Tuple&& t,
44  std::index_sequence<Is...>) {
45  return std::make_tuple(std::get<Is>(std::forward<Tuple>(t))...);
46 }
47 } // namespace internal
48 
49 template <size_t N, class Tuple>
50 constexpr decltype(auto) take_front(Tuple&& t) {
51  return internal::take_front_impl(std::forward<Tuple>(t),
52  std::make_index_sequence<N>{});
53 }
54 
55 namespace internal {
56 template <size_t N, class Tuple, size_t... Is>
57 constexpr decltype(auto) take_rest_impl(Tuple&& t, std::index_sequence<Is...>) {
58  return std::make_tuple(std::get<N + Is>(std::forward<Tuple>(t))...);
59 }
60 } // namespace internal
61 
62 template <size_t N, class Tuple>
63 constexpr decltype(auto) take_rest(Tuple&& t) {
64  constexpr auto len = std::tuple_size<std::remove_reference_t<Tuple>>::value;
65  return internal::take_rest_impl<N>(std::forward<Tuple>(t),
66  std::make_index_sequence<len - N>{});
67 }
68 
69 namespace internal {
70 template <class Tuple, size_t I>
71 constexpr decltype(auto) sum_tuple_impl(Tuple&& t, std::index_sequence<I>) {
72  return std::get<0>(std::forward<Tuple>(t));
73 }
74 
75 template <class Tuple, size_t... Is>
76 constexpr decltype(auto) sum_tuple_impl(Tuple&& t, std::index_sequence<Is...>) {
77  constexpr auto len = std::tuple_size<std::remove_reference_t<Tuple>>::value;
78  return std::get<0>(std::forward<Tuple>(t)) +
79  sum_tuple_impl(take_rest<1>(std::forward<Tuple>(t)),
80  std::make_index_sequence<len - 1>{});
81 }
82 } // namespace internal
83 
84 template <class Tuple>
85 constexpr decltype(auto) sum_tuple(Tuple&& t) {
86  constexpr auto len = std::tuple_size<std::remove_reference_t<Tuple>>::value;
87  return internal::sum_tuple_impl(std::forward<Tuple>(t),
88  std::make_index_sequence<len>{});
89 }
90 
91 namespace internal {
92 template <class Tuple1, class Tuple2, size_t... Is>
93 constexpr decltype(auto) zip_impl(Tuple1&& t1,
94  Tuple2&& t2,
95  std::index_sequence<Is...>) {
96  return std::make_tuple(
97  std::make_pair(std::get<Is>(std::forward<Tuple1>(t1)),
98  std::get<Is>(std::forward<Tuple2>(t2)))...);
99 }
100 } // namespace internal
101 
102 template <class Tuple1, class Tuple2>
103 constexpr decltype(auto) zip(Tuple1&& t1, Tuple2&& t2) {
104  constexpr auto len1 = std::tuple_size<std::remove_reference_t<Tuple1>>::value;
105  constexpr auto len2 = std::tuple_size<std::remove_reference_t<Tuple2>>::value;
106  static_assert(len1 == len2, "Two tuple lengths must be the same");
107  return internal::zip_impl(std::forward<Tuple1>(t1), std::forward<Tuple2>(t2),
108  std::make_index_sequence<len1>{});
109 }
110 
111 namespace internal {
112 template <class Tuple, size_t... Is>
113 constexpr decltype(auto) enumerate_impl(Tuple&& t, std::index_sequence<Is...>) {
114  return std::make_tuple(
115  std::make_pair(Is, std::get<Is>(std::forward<Tuple>(t)))...);
116 }
117 } // namespace internal
118 
119 template <class Tuple>
120 constexpr decltype(auto) enumerate(Tuple&& t) {
121  constexpr auto len = std::tuple_size<std::remove_reference_t<Tuple>>::value;
122  return internal::enumerate_impl(std::forward<Tuple>(t),
123  std::make_index_sequence<len>{});
124 }
125 } // namespace mgcpp
126 #endif // TUPLE_UTILS_HPP
decltype(auto) constexpr zip(Tuple1 &&t1, Tuple2 &&t2)
Definition: tuple_utils.hpp:103
decltype(auto) constexpr take_front_impl(Tuple &&t, std::index_sequence< Is... >)
Definition: tuple_utils.hpp:43
constexpr void apply_void(Tuple &&t, F &&f)
Definition: tuple_utils.hpp:35
Definition: adapter_base.hpp:12
decltype(auto) constexpr enumerate(Tuple &&t)
Definition: tuple_utils.hpp:120
Definition: shape.hpp:33
decltype(auto) constexpr take_rest_impl(Tuple &&t, std::index_sequence< Is... >)
Definition: tuple_utils.hpp:57
decltype(auto) constexpr take_front(Tuple &&t)
Definition: tuple_utils.hpp:50
decltype(auto) constexpr take_rest(Tuple &&t)
Definition: tuple_utils.hpp:63
decltype(auto) constexpr sum_tuple_impl(Tuple &&t, std::index_sequence< I >)
Definition: tuple_utils.hpp:71
decltype(auto) constexpr enumerate_impl(Tuple &&t, std::index_sequence< Is... >)
Definition: tuple_utils.hpp:113
constexpr void apply_void_impl(Tuple &&t, F &&f, std::index_sequence< Is... >)
Definition: tuple_utils.hpp:28
decltype(auto) constexpr sum_tuple(Tuple &&t)
Definition: tuple_utils.hpp:85
decltype(auto) constexpr apply_impl(Tuple &&t, F &&f, std::index_sequence< Is... >)
Definition: tuple_utils.hpp:12
decltype(auto) constexpr zip_impl(Tuple1 &&t1, Tuple2 &&t2, std::index_sequence< Is... >)
Definition: tuple_utils.hpp:93
decltype(auto) constexpr apply(Tuple &&t, F &&f)
Definition: tuple_utils.hpp:20