stlab 2.3.0
Modern, modular C++ algorithms, data structures, and concurrency primitives
Loading...
Searching...
No Matches
tuple_algorithm.hpp
Go to the documentation of this file.
1/*
2 Copyright 2015 Adobe
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 Author: Felix Petriconi
6*/
7
8/**************************************************************************************************/
9
10#ifndef STLAB_CONCURRENCY_TUPLE_ALGORITHM_HPP
11#define STLAB_CONCURRENCY_TUPLE_ALGORITHM_HPP
12
16
17#include <stlab/config.hpp> // for STLAB_VERSION_NAMESPACE_*
18
19// stdc++
20#include <cstddef> // for size_t
21#include <optional> // for optional
22#include <tuple> // for get, tuple, tuple_size, tuple_cat, tuple...
23#include <type_traits> // for is_same_v, conditional_t, conditional
24#include <utility> // for forward, index_sequence, declval, move
25
26/**************************************************************************************************/
27
28namespace stlab {
29STLAB_VERSION_NAMESPACE_BEGIN()
30
31
36
37/**************************************************************************************************/
38
39class placeholder {};
40
41/**************************************************************************************************/
42
43namespace detail {
44
45/**************************************************************************************************/
46
47template <std::size_t I, std::size_t L, typename T, typename Op>
48struct tuple_find_impl {
49 static auto find(const T& t, Op op) {
50 if (op(std::get<I>(t))) return I;
51 return tuple_find_impl<I + 1, L, T, Op>::find(t, op);
52 }
53};
54
55template <std::size_t L, typename T, typename Op>
56struct tuple_find_impl<L, L, T, Op> {
57 static auto find(const T&, Op) { return L; }
58};
59
60template <std::size_t I, std::size_t L, typename T, typename Op>
61struct tuple_for_each_impl {
62 static void for_each(T& t, Op& op) {
63 op(std::get<I>(t));
64 tuple_for_each_impl<I + 1, L, T, Op>::for_each(t, op);
65 }
66};
67
68template <std::size_t L, typename T, typename Op>
69struct tuple_for_each_impl<L, L, T, Op> {
70 static void for_each(T&, Op&) {}
71};
72
73template <std::size_t I, std::size_t L, typename T, typename Op>
74struct tuple_min_element_impl {
75 static void min_element(T& t, Op& op) {
76 op(std::get<I>(t));
77 tuple_min_element_impl<I + 1, L, T, Op>::min_element(t, op);
78 }
79};
80
81template <std::size_t I, std::size_t L>
82struct get_i_impl {
83 template <typename T, typename F, typename D>
84 static auto go(T& t, std::size_t index, F&& f, D&& default_v) {
85 if (index == I) return std::forward<F>(f)(std::get<I>(t));
86 return get_i_impl<I + 1, L>::go(t, index, std::forward<F>(f), std::forward<D>(default_v));
87 }
88};
89
90template <std::size_t L>
91struct get_i_impl<L, L> {
92 template <typename T, typename F, typename D>
93 static auto go(T&, std::size_t, F&&, D&& default_v) {
94 return std::forward<D>(default_v);
95 }
96};
97
98template <std::size_t I, std::size_t L>
99struct void_i_impl {
100 template <typename T, typename F>
101 static void go(T& t, std::size_t index, F&& f) {
102 if (index == I)
103 std::forward<F>(f)(std::get<I>(t));
104 else
105 void_i_impl<I + 1, L>::go(t, index, std::forward<F>(f));
106 }
107};
108
109template <std::size_t L>
110struct void_i_impl<L, L> {
111 template <typename T, typename F>
112 static void go(T&, std::size_t, F&&) {}
113};
114
115/**************************************************************************************************/
116
117} // namespace detail
118
119/**************************************************************************************************/
120/*
121 * Finds in a tuple an element that satisfies the given predicate and returns the tuple index.
122 * It returns an index beyond the last element if no element satisfies the predicate.
123 */
124template <typename T, typename Op>
125auto tuple_find(const T& t, Op op) -> std::size_t {
126 if constexpr (std::tuple_size_v<T> == 0)
127 return 1;
128 else
129 return detail::tuple_find_impl<0, std::tuple_size_v<T>, T, Op>::find(t, op);
130}
131
132/*
133 * Applies the given predicate on all tuple elements
134 */
135template <typename T, typename Op>
136void tuple_for_each(T& t, Op op) {
137 detail::tuple_for_each_impl<0, std::tuple_size_v<T>, T, Op>::for_each(t, op);
138}
139
140/*
141 * Gets from the tuple element at position index the value by applying the given predicate
142 * The default value is returned, if the index is equal or greater to tuple_size
143 */
144template <typename T, typename F, typename D>
145auto get_i(T& t, std::size_t index, F f, D&& default_v) {
146 return detail::get_i_impl<0, std::tuple_size_v<T>>::go(t, index, std::move(f),
147 std::forward<D>(default_v));
148}
149
150/*
151 * Applies at the tuple element at position index the the given predicate
152 */
153template <typename T, typename F>
154auto void_i(T& t, std::size_t index, F&& f) {
155 return detail::void_i_impl<0, std::tuple_size_v<T>>::go(t, index, std::forward<F>(f));
156}
157
158/**************************************************************************************************/
159
160namespace detail {
161
162/**************************************************************************************************/
163
164template <class F, class Tuple, std::size_t... I>
165constexpr auto apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>) -> decltype(auto) {
166 return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
167}
168
169template <class F, class Tuple, std::size_t... I>
170constexpr auto apply_optional_indexed_impl(F&& f, Tuple&& t, std::index_sequence<I...>)
171 -> decltype(auto) {
172 return std::forward<F>(f)(std::move(*std::get<I>(std::forward<Tuple>(t)))...);
173}
174
175/**************************************************************************************************/
176
177template <class Seq, class F, class Tuple>
178constexpr auto apply_optional_indexed(F&& f, Tuple&& t) -> decltype(auto) {
179 return detail::apply_optional_indexed_impl(std::forward<F>(f), std::forward<Tuple>(t), Seq());
180}
181
182/**************************************************************************************************/
183
184template <class T, std::size_t N>
185struct map_placeholder {
186 using type = std::index_sequence<N>;
187};
188
189template <std::size_t N>
190struct map_placeholder<placeholder, N> {
191 using type = std::index_sequence<>;
192};
193
194template <std::size_t N>
195struct map_placeholder<std::optional<placeholder>, N> {
196 using type = std::index_sequence<>;
197};
198
199/**************************************************************************************************/
200
201} // namespace detail
202
203/**************************************************************************************************/
204// type-function variant of std::tuple_cat
205template <typename... Ts>
206using tuple_cat_t = decltype(std::tuple_cat(std::declval<Ts>()...));
207
208/**************************************************************************************************/
209// type-function that takes a parameter pack and returns a std::tuple<Ts...>
210// where all T[i] == void have been removed.
211template <typename... Ts>
212using voidless_tuple =
213 tuple_cat_t<std::conditional_t<std::is_same_v<void, Ts>, std::tuple<>, std::tuple<Ts>>...>;
214
215/**************************************************************************************************/
216// type-function that takes a parameter pack and returns a std::tuple<Ts...>
217// where all T[i] == void have been replaced with stlab::placeholder.
218template <typename... Ts>
219using placeholder_tuple =
220 std::tuple<std::conditional_t<std::is_same_v<void, Ts>, placeholder, Ts>...>;
221
222/**************************************************************************************************/
223// type-function that takes a parameter pack and returns a std::tuple<std::optional<Ts>...>
224// where all T[i] == void have been replaced with stlab::placeholder.
225template <typename... Ts>
226using optional_placeholder_tuple =
227 std::tuple<std::optional<std::conditional_t<std::is_same_v<void, Ts>, placeholder, Ts>>...>;
228
229/**************************************************************************************************/
230// apply the tuple `t`as arguments to the function `f`. Placeholders are ignored.
231template <class F, class Tuple>
232constexpr auto apply_ignore_placeholders(F&& f, Tuple&& t) -> decltype(auto) {
233 return detail::apply_impl(std::forward<F>(f), std::forward<Tuple>(t),
234 std::make_index_sequence<std::tuple_size_v<Tuple>>());
235}
236
237/**************************************************************************************************/
238// remove_placeholder::function<Index>::type returns a std::index_sequence<Index> if the type at
239// Index is not a placeholder, otherwise it returns an empty std::index_sequence.
240template <class Tuple>
242 template <std::size_t Index>
243 struct function {
244 using type =
245 typename detail::map_placeholder<std::tuple_element_t<Index, Tuple>, Index>::type;
246 };
247};
248
249/**************************************************************************************************/
250// apply_indexed applies the tuple `t` as arguments to the function `f` using the index sequence
251// `Seq` to select the arguments.
252template <class Seq, class F, class Tuple>
253constexpr auto apply_indexed(F&& f, Tuple&& t) -> decltype(auto) {
254 return detail::apply_impl(std::forward<F>(f), std::forward<Tuple>(t), Seq());
255}
256
257/**************************************************************************************************/
258
260
261STLAB_VERSION_NAMESPACE_END()
262} // namespace stlab
263
264/**************************************************************************************************/
265
266#endif
Definition tuple_algorithm.hpp:39
Definition reverse.hpp:28
Definition tuple_algorithm.hpp:243
Definition tuple_algorithm.hpp:241