元组的 std::transform 等价物 [英] Equivalent of std::transform for tuples

查看:47
本文介绍了元组的 std::transform 等价物的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个函数,它的行为类似于元组的 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 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 等价物的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆