Instantly share code, notes, and snippets.

Embed
What would you like to do?
#include <tuple>
#include <utility>
#include <type_traits>
#include <iostream>
template<typename... T> class typelist {};
template<typename F, std::size_t I, typename... Tuples>
using apply_result_type = decltype(std::declval<F>()(std::get<I>(std::declval<Tuples>())...));
template<typename F, std::size_t... Indices, typename... Tuples>
typelist<apply_result_type<F, Indices, Tuples...>...> compute_result_types(typelist<F, Tuples...>, std::index_sequence<Indices...>);
template<typename F, std::size_t Size, typename... Tuples>
using result_types = decltype(compute_result_types(typelist<F, Tuples...>(), std::make_index_sequence<Size>()));
template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
template<typename... Ts>
all_true<!std::is_void<Ts>::value...> do_is_none_void(typelist<Ts...>);
template<typename TL>
using has_no_void_in_list = decltype(do_is_none_void(TL()));
template<size_t N, typename Function, typename... Tuples>
constexpr decltype(auto) tuple_for_each_aux(Function&& f, Tuples&&... ts)
{
return std::forward<Function>(f)(std::get<N>(std::forward<Tuples>(ts))...);
}
template<typename Function, typename... Tuples, std::size_t... Indices, typename = std::enable_if_t<!has_no_void_in_list<result_types<Function, sizeof...(Indices), Tuples...>>::value>>
constexpr void tuple_for_each_aux(Function&& f, std::index_sequence<Indices...>, Tuples&&... ts)
{
using swallow = int[];
static_cast<void>(swallow{ 0, (tuple_for_each_aux<Indices>(std::forward<Function>(f), std::forward<Tuples>(ts)...), void(), 0)... });
}
template<typename Function, typename... Tuples, std::size_t... Indices, typename = std::enable_if_t<has_no_void_in_list<result_types<Function, sizeof...(Indices), Tuples...>>::value>>
constexpr decltype(auto) tuple_for_each_aux(Function&& f, std::index_sequence<Indices...>, Tuples&&... ts)
{
return decltype(std::make_tuple(tuple_for_each_aux<Indices>(std::forward<Function>(f), std::forward<Tuples>(ts)...)...)) { tuple_for_each_aux<Indices>(std::forward<Function>(f), std::forward<Tuples>(ts)...)... };
}
template<typename Function, typename Tuple, typename... Tuples>
constexpr decltype(auto) tuple_for_each(Function&& f, Tuple&& t, Tuples&&... ts)
{
return tuple_for_each_aux(std::forward<Function>(f), std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}, std::forward<Tuple>(t), std::forward<Tuples>(ts)...);
}
struct functor
{
int operator()(int a, int b) { return a + b; }
double operator()(double a, double b) { return a + b; }
void operator()(char, char) { return; }
};
int main()
{
auto t1 = std::make_tuple(1, 2.0, 'a');
auto t2 = std::make_tuple(2, 4.0, 'b');
tuple_for_each(functor{}, t1, t2);
auto t3 = std::make_tuple(1, 2.0);
auto t4 = std::make_tuple(2, 4.0);
auto r = tuple_for_each(functor{}, t3, t4);
static_assert(std::is_same<decltype(r), std::tuple<int, double>>{}, "!!!");
std::cout << std::get<0>(r) << ' ' << std::fixed << std::get<1>(r) << '\n';
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment