【发布时间】:2018-10-13 21:36:13
【问题描述】:
我正在尝试将函数 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 和 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。扩容如何控制?还有,如何修复我的退货声明?
更新:
根据@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。
【问题讨论】:
标签: c++ templates variadic-templates c++17