gpt4 book ai didi

C++17 多参数包扩展

转载 作者:搜寻专家 更新时间:2023-10-31 00:08:44 25 4
gpt4 key购买 nike

我正在尝试映射函数 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。

最佳答案

从这里开始:

namespace utility {
template<std::size_t...Is>
auto index_over( std::index_sequence<Is...> ) {
return [](auto&& f)->decltype(auto) {
return decltype(f)(f)( std::integral_constant<std::size_t, Is>{}... );
};
}
template<std::size_t N>
auto index_upto( std::integral_constant<std::size_t, N> ={} ) {
return index_over( std::make_index_sequence<N>{} );
}
}

这让我们不必为了扩展一些参数包而编写一大堆函数。 index_upto<7>()([](auto...Is){ /* here */ })给你一个上下文,你有一堆编译时整数常量 0 到 6。

template<class F, class T0, class...Tuples>
auto map_over_tuples( F&& f, T0&... t0, Tuples&&... tuples ) {
using tuple_size = typename std::tuple_size< std::decay_t<T0> >::type;

auto get_element = [&](auto I){
return f(std::get<I>(std::forward<T0>(t0)), std::get<I>(std::forward<Tuples>(tuples)...));
};
return index_upto<tuple_size{}>()([&](auto...Is){
return std::make_tuple( get_element(Is)... );
});
}

在某些编译器中,使用 I必须替换为 decltype(I)::valueget_element .

关于C++17 多参数包扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47210956/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com