carl  24.04
Computer ARithmetic Library
tuple_util.h
Go to the documentation of this file.
1 /**
2  * @file tuple_util.h
3  * @author Gereon Kremer <gereon.kremer@cs.rwth-aachen.de>
4  */
5 
6 #pragma once
7 
8 #include <tuple>
9 
10 namespace carl {
11 
12 
13 namespace detail {
14  /**
15  * Helper method for carl::tuple_apply that actually performs the call.
16  */
17  template<typename Tuple1, typename Tuple2, std::size_t... I1, std::size_t... I2>
18  auto tuple_cat_impl(Tuple1&& t1, Tuple2&& t2, std::index_sequence<I1...> /*unused*/, std::index_sequence<I2...> /*unused*/) {
19  return std::make_tuple(std::get<I1>(std::forward<Tuple1>(t1))..., std::get<I2>(std::forward<Tuple2>(t2))...);
20  }
21 }
22 template<typename Tuple1, typename Tuple2>
23 auto tuple_cat(Tuple1&& t1, Tuple2&& t2) {
25  std::forward<Tuple1>(t1),
26  std::forward<Tuple2>(t2),
27  std::make_index_sequence<std::tuple_size<typename std::decay<Tuple1>::type>::value>{},
28  std::make_index_sequence<std::tuple_size<typename std::decay<Tuple2>::type>::value>{}
29  );
30 }
31 
32 namespace detail {
33  /**
34  * Helper method for carl::tuple_tail that actually performs the call.
35  */
36  template<typename Tuple, std::size_t... I>
37  auto tuple_tail_impl(Tuple&& t, std::index_sequence<I...> /*unused*/) {
38  return std::make_tuple(std::get<I+1>(std::forward<Tuple>(t))...);
39  }
40 }
41 
42 /**
43  * Returns a new tuple containing everything but the first element.
44  */
45 template<typename Tuple>
46 auto tuple_tail(Tuple&& t) {
47  return detail::tuple_tail_impl(std::forward<Tuple>(t), std::make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value-1>{});
48 }
49 
50 template<typename Converter, typename Information, typename FOut, typename... TOut>
52 private:
53  Information mInfo;
54  tuple_convert<Converter, Information, TOut...> conv;
55 public:
56  explicit tuple_convert(const Information& i): mInfo(i), conv(i) {}
57  template<typename Tuple>
58  std::tuple<FOut, TOut...> operator()(const Tuple& in) {
59  return std::tuple_cat(std::make_tuple(Converter::template convert<FOut>(std::get<0>(in), mInfo)), conv(tuple_tail(in)));
60  }
61 };
62 
63 template<typename Converter, typename Information, typename Out>
64 class tuple_convert<Converter, Information, Out> {
65 private:
66  Information mInfo;
67 public:
68  explicit tuple_convert(const Information& i): mInfo(i) {}
69  template<typename In>
70  std::tuple<Out> operator()(const std::tuple<In>& in) {
71  return std::make_tuple(Converter::template convert<Out>(std::get<0>(in), mInfo));
72  }
73 };
74 
75 namespace detail {
76  /**
77  * Helper method for carl::tuple_apply that actually performs the call.
78  */
79  template<typename F, typename Tuple, std::size_t... I>
80  auto tuple_apply_impl(F&& f, Tuple&& t, std::index_sequence<I...> /*unused*/) {
81  return (std::forward<F>(f))(std::get<I>(std::forward<Tuple>(t))...);
82  }
83 }
84 
85 /**
86  * Invokes a callable object f on a tuple of arguments.
87  * This is basically `std::apply` (available with C++17).
88  */
89 template<typename F, typename Tuple>
90 auto tuple_apply(F&& f, Tuple&& t) {
91  return detail::tuple_apply_impl(std::forward<F>(f), std::forward<Tuple>(t), std::make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{});
92 }
93 
94 
95 namespace detail {
96  /**
97  * Helper method for carl::tuple_foreach that actually does the work.
98  */
99  template<typename F, typename Tuple, std::size_t... I>
100  auto tuple_foreach_impl(F&& f, Tuple&& t, std::index_sequence<I...> /*unused*/) {
101  return std::make_tuple(f(std::get<I>(std::forward<Tuple>(t)))...);
102  }
103 }
104 
105 /**
106  * Invokes a callable object f on every element of a tuple and returns a tuple containing the results.
107  * This basically corresponds to the functional `map(func, list)`.`
108  */
109 template<typename F, typename Tuple>
110 auto tuple_foreach(F&& f, Tuple&& t) {
111  return detail::tuple_foreach_impl(std::forward<F>(f), std::forward<Tuple>(t), std::make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{});
112 }
113 
114 namespace detail {
115  /**
116  * Helper functor for carl::tuple_accumulate that actually does the work.
117  */
118  template<typename Tuple, typename T, typename F>
120  template<std::size_t I, typename std::enable_if<0 < I, void>::type* = nullptr>
121  T call(Tuple&& t, T&& init, F&& f) {
122  return std::forward<F>(f)(call<I-1>(t, init, std::forward<F>(f)), std::get<I-1>(t));
123  }
124  template<std::size_t I, typename std::enable_if<0 == I, void>::type* = nullptr>
125  T call(Tuple&& t, T&& init, F&& f) {
126  return init;
127  }
128  T operator()(Tuple&& t, T&& init, F&& f) {
129  return call<std::tuple_size<typename std::decay<Tuple>::type>::value>(t, init, std::forward<F>(f));
130  }
131  };
132 }
133 
134 /**
135  * Implements a functional fold (similar to `std::accumulate`) for `std::tuple`.
136  * Combines all tuple elements using a combinator function `f` and an initial value `init`.
137  */
138 template<typename Tuple, typename T, typename F>
139 T tuple_accumulate(Tuple&& t, T&& init, F&& f) {
140  return detail::tuple_accumulate_impl<Tuple,T,F>()(t, init, std::forward<F>(f));
141 }
142 
143 }
carl is the main namespace for the library.
auto tuple_cat(Tuple1 &&t1, Tuple2 &&t2)
Definition: tuple_util.h:23
auto tuple_apply(F &&f, Tuple &&t)
Invokes a callable object f on a tuple of arguments.
Definition: tuple_util.h:90
auto tuple_tail(Tuple &&t)
Returns a new tuple containing everything but the first element.
Definition: tuple_util.h:46
T tuple_accumulate(Tuple &&t, T &&init, F &&f)
Implements a functional fold (similar to std::accumulate) for std::tuple.
Definition: tuple_util.h:139
int init()
The routine for initializing the carl library.
Definition: initialize.h:31
auto tuple_foreach(F &&f, Tuple &&t)
Invokes a callable object f on every element of a tuple and returns a tuple containing the results.
Definition: tuple_util.h:110
auto tuple_apply_impl(F &&f, Tuple &&t, std::index_sequence< I... >)
Helper method for carl::tuple_apply that actually performs the call.
Definition: tuple_util.h:80
auto tuple_tail_impl(Tuple &&t, std::index_sequence< I... >)
Helper method for carl::tuple_tail that actually performs the call.
Definition: tuple_util.h:37
auto tuple_foreach_impl(F &&f, Tuple &&t, std::index_sequence< I... >)
Helper method for carl::tuple_foreach that actually does the work.
Definition: tuple_util.h:100
auto tuple_cat_impl(Tuple1 &&t1, Tuple2 &&t2, std::index_sequence< I1... >, std::index_sequence< I2... >)
Helper method for carl::tuple_apply that actually performs the call.
Definition: tuple_util.h:18
std::tuple< FOut, TOut... > operator()(const Tuple &in)
Definition: tuple_util.h:58
tuple_convert< Converter, Information, TOut... > conv
Definition: tuple_util.h:54
Information mInfo
Definition: tuple_util.h:53
tuple_convert(const Information &i)
Definition: tuple_util.h:56
std::tuple< Out > operator()(const std::tuple< In > &in)
Definition: tuple_util.h:70
Helper functor for carl::tuple_accumulate that actually does the work.
Definition: tuple_util.h:119