10#ifndef STLAB_CONCURRENCY_TUPLE_ALGORITHM_HPP
11#define STLAB_CONCURRENCY_TUPLE_ALGORITHM_HPP
17#include <stlab/config.hpp>
29STLAB_VERSION_NAMESPACE_BEGIN()
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);
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; }
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) {
64 tuple_for_each_impl<I + 1, L, T, Op>::for_each(t, op);
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&) {}
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) {
77 tuple_min_element_impl<I + 1, L, T, Op>::min_element(t, op);
81template <std::
size_t I, std::
size_t L>
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));
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);
98template <std::
size_t I, std::
size_t L>
100 template <
typename T,
typename F>
101 static void go(T& t, std::size_t index, F&& f) {
103 std::forward<F>(f)(std::get<I>(t));
105 void_i_impl<I + 1, L>::go(t, index, std::forward<F>(f));
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&&) {}
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)
129 return detail::tuple_find_impl<0, std::tuple_size_v<T>, T, Op>::find(t, op);
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);
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));
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));
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))...);
169template <
class F,
class Tuple, std::size_t... I>
170constexpr auto apply_optional_indexed_impl(F&& f, Tuple&& t, std::index_sequence<I...>)
172 return std::forward<F>(f)(std::move(*std::get<I>(std::forward<Tuple>(t)))...);
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());
184template <
class T, std::
size_t N>
185struct map_placeholder {
186 using type = std::index_sequence<N>;
189template <std::
size_t N>
190struct map_placeholder<placeholder, N> {
191 using type = std::index_sequence<>;
194template <std::
size_t N>
195struct map_placeholder<std::optional<placeholder>, N> {
196 using type = std::index_sequence<>;
205template <
typename... Ts>
206using tuple_cat_t =
decltype(std::tuple_cat(std::declval<Ts>()...));
211template <
typename... Ts>
212using voidless_tuple =
213 tuple_cat_t<std::conditional_t<std::is_same_v<void, Ts>, std::tuple<>, std::tuple<Ts>>...>;
218template <
typename... Ts>
219using placeholder_tuple =
220 std::tuple<std::conditional_t<std::is_same_v<void, Ts>,
placeholder, Ts>...>;
225template <
typename... Ts>
226using optional_placeholder_tuple =
227 std::tuple<std::optional<std::conditional_t<std::is_same_v<void, Ts>,
placeholder, Ts>>...>;
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>>());
240template <
class Tuple>
242 template <std::
size_t Index>
245 typename detail::map_placeholder<std::tuple_element_t<Index, Tuple>, Index>::type;
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());
261STLAB_VERSION_NAMESPACE_END()
Definition tuple_algorithm.hpp:39
Definition reverse.hpp:28
Definition tuple_algorithm.hpp:243
Definition tuple_algorithm.hpp:241