【发布时间】:2017-03-29 09:55:44
【问题描述】:
由于 range-library 已被纳入标准,因此我一直在玩弄它,但我在非常基本的概念方面遇到了一些问题。
我正在努力解决的玩具示例是这样的:
#include <iostream>
#include <range/v3/all.hpp>
using namespace ranges;
int main (int argc, char const* argv[]) {
auto v = view::iota(1, 10);
std::default_random_engine gen;
auto t = action::push_back(view::iota(0, 10)) | action::shuffle(gen);
std::cout << t << "\n";
}
它不可打印的事实向我表明,t 并不是一个真正合适的范围。不幸的是,文档(有的话)确实滥用了 auto,所以我不知道发生了什么。我必须做什么,为什么我必须这样做(如果有人知道:结果类型将如何记录(imo 代理对象和 auto 不能很好地混合 - 以 Eigen 库为例) ))。
我的第二个问题与货物崇拜的 action::push_back 有关。如果我省略它,我会收到一个概念错误,告诉我 iota 生成的视图需要是可变的。显然,视图在设计上是不可变的,所以我在这里遇到了问题,但是“什么都不做”真的是将事物提升到可变/有状态对象的首选方式还是有其他选择?
最好, 理查德
【问题讨论】:
-
我不使用范围库,但我也对它感兴趣 :) 你能输入编译器诊断信息吗? AFAIK 迭代器是延迟创建的。所以可能你不能洗牌 view::iota,因为数据不像向量中那样存在。您是否尝试过从 view::iota 生成一个向量,然后对其进行洗牌?
-
push_back 正是这样做的。我只是想知道这是否是规范的方法。范围库背后的想法通常被称为流/流融合。您在惰性容器上工作,直到某个时刻(希望是最后)出现一个表现步骤(实际执行和编写)。表现通常使用一些折叠或一些副本来完成。 ::push_back 似乎是后者的(主观上)奇怪的选择。因此我的第二个问题。最终我对动作的解释是错误的,这就是为什么 Caleth 的回答真的很有帮助。
-
操作在容器上操作,而不是视图。您需要使您的
iota_view具体化-例如使用to_vector- 在将其传递给shuffle之前。 Tryauto container = view::iota(1, 10) | to_vector | action::shuffle(gen);.