diff --git a/src/tuple.hpp b/src/tuple.hpp new file mode 100644 index 0000000..fa90908 --- /dev/null +++ b/src/tuple.hpp @@ -0,0 +1,120 @@ +#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>>()); +} +}; // namespace tp diff --git a/src/utils.hpp b/src/utils.hpp new file mode 100644 index 0000000..40b13ae --- /dev/null +++ b/src/utils.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +template constexpr std::string_view type_name() { + using namespace std; +#ifdef __clang__ + string_view p = __PRETTY_FUNCTION__; + return string_view(p.data() + 34, p.size() - 34 - 1); +#elif defined(__GNUC__) + string_view p = __PRETTY_FUNCTION__; +# if __cplusplus < 201402 + return string_view(p.data() + 36, p.size() - 36 - 1); +# else + return string_view(p.data() + 49, p.find(';', 49) - 49); +# endif +#elif defined(_MSC_VER) + string_view p = __FUNCSIG__; + return string_view(p.data() + 84, p.size() - 84 - 7); +#endif +}