首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >合并std::view::take pop_front pop_back

合并std::view::take pop_front pop_back
EN

Stack Overflow用户
提问于 2022-07-30 18:25:42
回答 2查看 87关注 0票数 0

我不知道如何将take与从容器中移除所获取的元素的操作巧妙地结合起来。

考虑一下下面是代码:

代码语言:javascript
复制
static constexpr int kBatchSize = 4;
void fn(std::deque<int>& vals) {
    const auto elems = std::views::take(vals, kBatchSize);
    fmt::print("\n[");
    for (const auto& elem : elems) {
        fmt::print("{} ", elem);
    }
    fmt::print("]\n");

    for ([[maybe_unused]] const auto&_:elems) {
        vals.pop_front();
    }
}

它工作得很好(AFAIK),但我需要额外的迭代,因为我无法找到一种将元素的提取和删除结合起来的方法。

注意:fmt::print只是每个元素逻辑的一个例子,请不要关注这样一个事实,即这可以以更好的方式完成。在实际的代码函数中,不是简单的打印。

是否有一种优雅的方法将其合并成一次传递?

EN

回答 2

Stack Overflow用户

发布于 2022-07-30 19:36:38

视图不能修改容器;它们的任务是成为范围的视图。

如果您只想遍历第一个X元素,然后删除所有元素(除非您想要复制这些元素,它就必须按照这个顺序进行),那么使用std::for_each_n很容易做到这一点

代码语言:javascript
复制
void fn(std::deque<int>& vals)
{
    fmt::print("\n[");
    auto end_it = std::for_each_n(vals.begin(), kBatchSize, [](int const& elem){
        fmt::print("{} ", elem);
    });
    fmt::print("]\n");

    vals.erase(vals.begin(), end_it);
}
票数 1
EN

Stack Overflow用户

发布于 2022-07-30 20:03:36

您可以在不修改vals的情况下做到这一点。例如,通过将vals转换为subrange并将每次时间分配给subrange

代码语言:javascript
复制
#include <deque>
#include <ranges>
#include <fmt/ranges.h>

static constexpr int kBatchSize = 4;
auto fn(std::ranges::view auto vals) {
  const auto elems = std::views::take(vals, kBatchSize);
  fmt::print("{}\n", elems);

  return vals | std::views::drop(kBatchSize);
}

int main() {
  std::deque vals{1,2,3,4,5,6};
  auto res = fn(std::ranges::subrange{vals}); // [1, 2, 3, 4]
  res = fn(res); // [5, 6]
  res = fn(res); // []
}

演示

之所以可以这样做,是因为std::views::takestd::views::dropsubranges有专门化,这要归功于P1739,也就是说,它们返回一个大小正确的subrange

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73178117

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档