问题描述
我想要一个函数,其行为类似于元组的 std::transform.基本上要实现的功能是
I want a function that will behave like std::transform
for tuples. Basically the functionality to be implemented is
template<size_t From, size_t To, class Tuple, class Func>
void tuple_transform(Tuple&& source, Tuple&& target, Func f)
{
// elements <From, To> of `target` ti become `f(si)`, where
// si is the corresponding element of `source`
};
我相信要实现这一点,我需要一个 编译时整数范围 结构,它是 std::index_sequence
的泛化,我已经实现了它这里 与 cti::range
.我也相信这种类型的编译时间遍历在这里是理想的:
I believe that to implement this I'll need a compile time integer range struct, a generalization of std::index_sequence
and I've implemented it here with cti::range
. I also believe that this type of compile time traversal is ideal here :
template<class Func, class Tuple, size_t...Is>
void for_each_in_tuple(Func f, Tuple&& tuple, std::index_sequence<Is...>){
using expander = int[];
(void)expander { 0, ((void)f(std::get<Is>(std::forward<Tuple>(tuple))), 0)... };
}
template<class Func, class Tuple>
void for_each_in_tuple(Func f, Tuple&& tuple){
for_each_in_tuple(f, std::forward<Tuple>(tuple),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>());
}
任何人都可以帮助我实施吗?
Can anyone help me with the implementation ?
@MohitJain 与链接的代码 (tuple_transform) 一样,没有考虑到这一点(Func
具有单一类型).如果这样解决,我可以通过传递模板模板参数 template<class> 轻松扩展它.class Func
并要求我的转换类型是这样的
@MohitJain Like in the code linked (tuple_transform) this is not taken into account (Func
has a single type). If this is solved like that, I could easily extend it by passing a template template parameter template<class> class Func
and mandate that my transformation types are like this
template<typename T>
struct Func
{
static void apply(T& val) { ... }
}
然后在元组变换的主体内,每个变换函数可以这样调用:
then inside the body of tuple transform, each transformation func could be called like :
get<I>(target) = func<typename tuple_element<I, Tuple>::type>::apply(get<I>(source))
<小时>
编辑
刚刚在 accu 2015 上进行了一次闪电演讲.以上是演示结束时的 CodeKata.我将在 这里 留下演示文稿,希望它对任何实施都有帮助尝试(我认为几乎所有需要的工具都已提供,因此我们将对此进行更多尝试)
EDIT
Just gave a lightning talk @ accu 2015. The above was the CodeKata at the end of the presentation. I'll leave here the presentation, hopefullly it'll help with any implementation attempts (I think pretty much every tool required is presented, so we'll have more attempts at this)
推荐答案
这是一个使用 index_range 的解决方案模板整数范围">这里.
Here's a solution that uses index_range
from here.
template<size_t SN, size_t DN, class TSrc, class TDest, class Func>
void tuple_call_assign(TSrc&& source, TDest& target, Func f)
{
std::get<DN>(target) = f(std::get<SN>(std::forward<TSrc>(source)));
}
template<size_t From, size_t To, class TSrc, class TDest, class Func, size_t...Is, size_t...DIs>
void tuple_transform(TSrc&& source, TDest& target, Func f,
std::index_sequence<Is...>, std::index_sequence<DIs...>)
{
using expander = int[];
(void)expander { 0, (tuple_call_assign<Is,DIs>(std::forward<TSrc>(source),target,f), 0)... };
}
template<size_t From, size_t To, size_t FromDest, class TSrc, class TDest, class Func>
void tuple_transform(TSrc&& source, TDest& target, Func f)
{
static_assert(To > From, "Range must be increasing");
static_assert(To <= std::tuple_size<std::decay_t<TSrc>>::value+1,
"Range must be valid for source tuple");
constexpr size_t RangeSize = To-From;
static_assert(FromDest+RangeSize <= std::tuple_size<std::decay_t<TDest>>::value,
"Range must be valid for target tuple");
tuple_transform<From,To>(std::forward<TSrc>(source), target, f,
index_range<From,To>(), index_range<FromDest, FromDest+RangeSize>());
}
演示
这需要第三个模板参数来指定要转换为目标元组的起始索引.
This takes a third template argument to specify a starting index to transform into the target tuple.
这篇关于等价于元组的 std::transform的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!