我正在尝试映射函数f
元组之上t0
, t1
等返回元组std::tuple<f(std::get<0>(t0),std:get<0>(t1),...),f(std::get<1>(t0),std::get<1>(t1),...),...)
。我有一个正在使用的版本car
,cdr
, and cons
但我正在尝试使用一个版本std::index_sequence
.
代码:
// Helper
template<typename T>
using make_tuple_index = std::make_index_sequence<std::tuple_size<T>::value>;
// Implementation
template<typename F, typename... Ts, std::size_t... Is>
auto mapx_n_impl(const F& f, std::index_sequence<Is...>, const Ts&... t)
{ return std::make_tuple(f(std::get<Is>(t...))...); }
// Interface
template<typename T,
typename F,
typename Indices = make_tuple_index<T>>
auto map(const T& t, const F& f)
{ return mapx_impl(t, f, Indices{}); }
// Test
auto tup1 = std::make_tuple(1.0, 2.0, 3.0);
auto tup2 = std::make_tuple(0.0, 1.0, 2.0);
auto r = mapx_n([](auto x, auto y) { return x - y; }, tup1, tup2);
问题在于扩展实现返回语句中的参数包。我需要它来扩展t
在“内部”循环中和Is
在“外”循环中。扩张是如何控制的?而且,我该如何修改我的退货单?
UPDATE:
根据@Yakk的回复和@max66的进一步说明,我尽可能地简化了我的代码。当前版本集成了 @Yakk 答案中的参数包扩展助手版本,并将 get_element 调用分解为 lambda。
// invoke_with_pack
template<std::size_t... Is, typename F>
auto invoke_with_pack(std::index_sequence<Is...>, F&& function)
{ return function(std::integral_constant<std::size_t, Is>{}...); }
// nth
template<natural N, typename... Ts>
using nth = typename std::tuple_element<N, std::tuple<Ts...>>::type;
// make_tuple_index -- Helper template for computing indices
// corresponding to a tuple.
template<typename T>
using make_tuple_index = std::make_index_sequence<std::tuple_size<T>::value>;
// map_n -- Map <function> over <tuples> t0,t1,...
template<typename F,
typename... Ts,
typename Indices = make_tuple_index<nth<0,Ts...>>>
auto map_n(F&& function, Ts&... tuples)
{
auto get_element = [&](auto I) { return function(std::get<I>(tuples)...); };
return invoke_with_pack(Indices{}, [&](auto... Is) {
return std::make_tuple(get_element(Is)...);
});
}
现在来弄清楚如何使用索引而不是 car、cdr 和 cons 来实现 Fold_left 和 Fold_right。