Я хочу реализовать функцию, которая отображает вариационный список кортежей в другой кортеж, заданный функцией.Как реализовать переменную операцию tuple_map?
Он применяет N-арную функцию f
к списку элементов, взятых из списка из N кортежей (каждый с размером не менее M) и создает новый кортеж M-элементов из результата этих приложений.
Списка N кортежей, каждый из М элементов, вызов std::make_tuple
будет выглядеть следующим образом псевдокода:
std::make_tuple(
f(t1_1, t2_1, t3_1, ..., tN_1),
f(t1_2, t2_2, t3_2, ..., tN_2),
f(t1_3, t2_3, t3_3, ..., tN_3),
...
f(t1_M, t2_M, t3_M, ..., tN_M)
)
Иногда эта операция называется zipWith
на других языках.
Я хочу, чтобы эта функция, tuple_map
, чтобы иметь следующую подпись:
template<class Tuple1, class... Tuples2, class Function>
auto tuple_map(Tuple1&& tuple1, Tuples&&... tuples, Function f);
Я понял, реализацию функции, принимая один кортеж:
#include <tuple>
#include <integer_sequence>
#include <type_traits>
#include <utility>
template<class Tuple, class Function, size_t... I>
auto tuple_map_impl(Tuple&& t, Function f, std::index_sequence<I...>)
-> decltype(
std::make_tuple(
f(std::get<I>(std::forward<Tuple>(t)))...
)
)
{
return std::make_tuple(
f(std::get<I>(std::forward<Tuple>(t)))...
);
}
template<class Tuple, class Function>
auto tuple_map(Tuple&& t, Function f)
-> decltype(
tuple_map_impl(
std::forward<Tuple>(t),
f,
std::make_index_sequence<
std::tuple_size<std::decay_t<Tuple>>::value
>()
)
)
{
using indices = std::make_index_sequence<
std::tuple_size<std::decay_t<Tuple>>::value
>;
return tuple_map_impl(std::forward<Tuple>(t), indices());
}
Когда я ввожу другой (Tuples
) в дополнение к I...
, это вызывает проблемы:
template<class Tuple1, class... Tuples, class Function, size_t... I>
auto tuple_map_impl(Tuple1&& tuple1, Tuples&&... tuples, Function f, std::index_sequence<I...>)
-> decltype(
std::make_tuple(
f(
std::get<I>(std::forward<Tuple1>(t1)),
std::get<I>(std::forward<Tuples>(tuples))...
)...
)
)
{
return std::make_tuple(
f(
std::get<I>(std::forward<Tuple>(t)),
std::get<I>(std::forward<Tuples>(tuples))...
)...
);
}
Компилятор ошибка:
error: mismatched argument pack lengths while expanding ‘get<I>(forward<Tuples>(tuples))’
Это потому, что я использовал две пачки с разными длинами (I
и Tuples
) в пределах того же выражения.
Я не могу придумать другой способ написать эту функцию, которая не использовала бы две упаковки в одном выражении.
Каков наилучший способ реализации tuple_map
?
Вы можете дать полную спецификацию первых, говоря, что функция * должна * делать? –
В соответствии с принятым ответом на самом деле вам нужна функция, которая * применяет функцию 'N'-ary f к списку элементов, взятых из списка кортежей' N' (каждый с размером 'M') и создает новый' M'-элементный кортеж из результата этих приложений. * –
Спасибо за улов! –