#pragma once #include #include #include #include #include #include #include #include namespace tp { namespace detail { template constexpr Func for_each_arg(Func f, Args &&...args) { (f(std::forward(args)), ...); return f; } template constexpr Func for_each_impl(Tuple &&t, Func &&f, std::index_sequence is) { (std::forward(f)(std::get(std::forward(t))), ...); return f; } template auto transform_impl(std::tuple const &inputs, Function function, std::index_sequence is) { return std::tuple...>{function(std::get(inputs))...}; } template auto subtuple(const std::tuple &t, std::index_sequence) { return std::make_tuple(std::get(t)...); } // ZIP utilities template using zip_tuple_at_index_t = std::tuple>...>; template zip_tuple_at_index_t zip_tuple_at_index(Tuples &&...tuples) { return {std::get(std::forward(tuples))...}; } template std::tuple...> tuple_zip_impl(Tuples &&...tuples, std::index_sequence) { return {zip_tuple_at_index(std::forward(tuples)...)...}; } }; // namespace detail template constexpr decltype(auto) for_each(Tuple &&tuple, F &&f) { return [](Tuple &&tuple, F &&f, std::index_sequence) { (f(std::get(tuple)), ...); return f; }(std::forward(tuple), std::forward(f), std::make_index_sequence>::value>{}); } template auto transform(std::tuple const &inputs, Function function) { return detail::transform_impl(inputs, function, std::make_index_sequence{}); } template constexpr size_t find_if(Tuple &&tuple, Predicate pred) { size_t index = std::tuple_size>::value; size_t currentIndex = 0; bool found = false; for_each(tuple, [&](auto &&value) { if (!found && pred(value)) { index = currentIndex; found = true; } ++currentIndex; }); return index; } template void perform(Tuple &&tuple, size_t index, Action action) { size_t currentIndex = 0; for_each(tuple, [&action, index, ¤tIndex](auto &&value) { if (currentIndex == index) { action(std::forward(value)); } ++currentIndex; }); } template bool all_of(Tuple &&tuple, Predicate pred) { return find_if(tuple, std::not_fn(pred)) == std::tuple_size>::value; } template bool none_of(Tuple &&tuple, Predicate pred) { return find_if(tuple, pred) == std::tuple_size>::value; } template bool any_of(Tuple &&tuple, Predicate pred) { return !none_of(tuple, pred); } template Tuple &operator|(Tuple &&tuple, Function func) { for_each(tuple, func); return tuple; } template auto subtuple(const std::tuple &t) { return detail::subtuple(t, std::make_index_sequence()); } template ())> struct sub_range; template struct sub_range, std::index_sequence> { static_assert(elems <= sizeof...(Args) - starting, "sub range is out of bounds!"); using tuple = std::tuple>...>; }; template auto select_tuple(Tuple &&tuple, std::index_sequence) { return std::tuple...>(std::get(std::forward(tuple))...); } template struct tuple_index; template struct tuple_index> { static const std::size_t value = 0; }; template struct tuple_index> { static const std::size_t value = 1 + tuple_index>::value; }; // ZIP template requires((std::tuple_size_v> == std::tuple_size_v>) && ...) auto tuple_zip(Head &&head, Tail &&...tail) { return detail::tuple_zip_impl(std::forward(head), std::forward(tail)..., std::make_index_sequence>>()); } // TAIL template struct tuple_tail; template struct tuple_tail> { using type = std::tuple; }; // }; // namespace tp