【问题标题】:How to concat two existing ranges::view?如何连接两个现有范围::view?
【发布时间】:2017-04-02 14:27:31
【问题描述】:

我想使用现有视图进行连接。在代码中:

auto rng = view::empty<vector<int>>();

for(int i{0}; i < 5; ++i)
{
    vector<int> const & v{foo()}; // returns a reference
    rng |= view::concat(v); // doesn't compile - error: no viable overloaded '|='
};

换句话说 - 我如何为多个直到运行时才知道数量的向量创建视图?

【问题讨论】:

  • newRange 是什么类型,我们可以看到foo() 函数吗?还有v 是干什么用的?
  • @Galik 我更新了代码。 foo() 函数返回一个 const 引用,但它与我的问题无关。
  • 我认为用范围很难做到这一点。考虑具有不同元素的 n 个范围。现在整个范围的 begin() 和 end() 指向第一个的 begin() 和最后一个的 end() ,在它之间必须跟踪我们是否在第 k 个范围的末尾,并且移动到第 (k+1) 个。 view::concat 在编译时通过大量机器实现了这一点。

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


【解决方案1】:

您不能以这种方式组合视图。连接一个视图会产生一个具有不同类型的对象。您不能将其分配回原始视图,因为它的类型不同。

您可以使用view::cycle(取一个范围并无限重复)和view::take(取一个范围的前N个元素)的组合来获得您想要的效果.

vector<int> const & v{foo()}; // returns a reference
auto rng = v | view::cycle | view::take(5 * v.size());

编辑

如果foo()每次都可以返回对不同向量的引用,那么除了view::take之外,您还可以使用view::generateview::join

auto rng = view::generate(foo) | view::take(5) | view::join;

【讨论】:

  • 如果foo() 从多个调用返回不同的向量,这将不会做你想做的事。您需要一个展平 (view::join?) 操作来组合它
  • @Eric 这可以用类型擦除的迭代器范围来完成吗? (这当然需要更改 range-v3 库代码)。但基本上我们有一个范围,它有一个开始/结束,并在内部保留一个开始和结束值的列表/压缩包。在迭代时,它会跟踪第 k 个范围并在最后移动到第 (k+1) 个。顺便说一句,这与双端队列的实现方式非常相似。这可以用来建模 RandomAccessIterator。这一切是否有用是另一回事:)
  • @skgbanga,是的,这可以通过类型擦除来完成,但我不建议这样做。
  • 谢谢你,对于我的例子它有效。但是如果我有一个向量列表(std::vector&lt;std::vector&lt;int&gt;&gt;)呢?如何为所有(或可能仅对某些)向量创建单个视图?甚至更好 - 如果我有一个期货列表并且每个未来都返回一个对向量的引用。
猜你喜欢
  • 2018-12-18
  • 2022-08-17
  • 2011-06-04
  • 1970-01-01
  • 2017-08-17
  • 2022-11-02
  • 2018-12-19
  • 2012-12-15
相关资源
最近更新 更多