【问题标题】:Replacing data with range-v3用 range-v3 替换数据
【发布时间】:2023-04-04 17:29:01
【问题描述】:

TL;DR

怎么可能得到相同的结果

std::copy(std::begin(a), std::end(a), std::begin(b));

使用 range-v3,可能还有它不错的语法?

编辑

我遇到麻烦的原因是对如何正确使用ranges::copy的误解:第二个参数必须是迭代器,而不是范围对象。我的错;)

尽管如此,我仍然在询问是否可以使用某种语法糖来执行范围分配,如下所示:

ranges::???(b) = a | op1 | op2 | ... ; 

问题

我有两个固定大小的向量(在运行时)。我需要对第一个向量中的数据执行一些复杂 转换,并将结果存储在第二个向量中。我需要保留第一个向量,我不想创建一个新的临时向量。

常用代码

using namespace std;
vector<double> a;
...
vector<double> b(a.size());

带标准

transform(begin(a), end(a), begin(b), complexFun);

混合标准范围 v3

auto transformation = a | ranges::view::transform(complexFun);
copy(begin(transformation), end(transformation), begin(b));

在这种简单的情况下,这样做有点不必要。但是,如果涉及多个操作,则使用 std::copy 创建范围视图特别有用。

我想写什么

ranges::???(b) = a | ranges::view::transform(complexFun);

我期待的是这个功能已经存在,但我找不到它。

【问题讨论】:

    标签: c++ c++11 c++14 range-v3


    【解决方案1】:

    怎么样:

    ranges::transform(a, b.begin(), complexfun);
    

    ?

    编辑: ...或者也许

    ranges::copy( a | ranges::views::transform(complexFun), begin(b) );
    

    ?

    【讨论】:

    • 如果我想使用多个视图怎么办?愚蠢的事情:用 complexFun 转换 a,然后将索引(使用 iota)添加到结果并存储到 b?
    • 好的,我刚刚得到了我的概念错误:我试图使用“b”作为ranges::copy 的第二个参数,而不是使用begin(b)。如果你想说这是问题所在,我会接受你的回答。尽管如此,是否有任何语法糖可以避免 range::copy 并将惰性视图“分配”到输出范围?
    【解决方案2】:

    有几个很好的方法可以做到这一点。首先,如果您还没有目标 vector 并且想要创建它:

    auto b = a | ranges::view::transform(complexFun) | ranges::to_vector;
    

    其次,如果您已经有一个目标vector,您想要重用其容量:

    b.clear(); // Assuming b already contains junk
    b |= ranges::action::push_back(a | ranges::view::transform(complexFun));
    

    在这两种情况下,range-v3 都足够聪明,可以在目标向量中为 ranges::size(a | ranges::view::transform(complexFun)) 元素保留容量,以避免由于重新分配而导致的复制。

    【讨论】:

    • 这不是一个理想的情况:你要为每次推送增加 b 的大小付出代价。我正在寻找的解决方案必须等同于混合案例,零开销。
    • @dodomorandi 你读过最后一段吗?它告诉您b 将被提前保留,不会发生重新分配。
    • @bolov 正如我所说,您没有任何分配,但您仍在操作对象数量的计数器。这是一个很小的代价,但在这种情况下仍然是多余的。
    • @bolov 对,我忘记了使用push 时有大量 的优化失误。良好的矢量化就是其中之一。如果你不相信我,just measure it.
    • ranges::action::push_back(v, r),当r是一个范围时,用v.insert(v.end(), begin(r), end(r))实现。如果您的 STL 实现物有所值,这应该是可矢量化的。
    猜你喜欢
    • 2019-12-16
    • 2021-03-04
    • 2020-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 2019-08-13
    相关资源
    最近更新 更多