【发布时间】:2019-01-04 22:40:18
【问题描述】:
我正在尝试将多个迭代器用于更复杂的范围(使用 range-v3 库)——手动实现笛卡尔积,使用 filter、for_each 和 yield。但是,当我尝试将多个迭代器保持在这样的范围内时,它们共享一个共同的值。例如:
#include <vector>
#include <iostream>
#include <range/v3/view/for_each.hpp>
#include <range/v3/view/filter.hpp>
int main() {
std::vector<int> data1{1,5,2,7,6};
std::vector<int> data2{1,5,2,7,6};
auto range =
data1
| ranges::v3::view::filter([](int v) { return v%2; })
| ranges::v3::view::for_each([&data2](int v) {
return data2 | ranges::v3::view::for_each([v](int v2) {
return ranges::v3::yield(std::make_pair(v,v2));
});
});
auto it1 = range.begin();
for (auto it2 = range.begin(); it2 != range.end(); ++it2) {
std::cout << "[" << it1->first << "," << it1->second << "] [" << it2->first << "," << it2->second << "]\n";
}
return 0;
}
我希望迭代器 it1 一直指向范围的开头,而迭代器 it2 则遍历整个序列。令我惊讶的是,it1 也增加了!我得到以下输出:
[1,1] [1,1]
[1,5] [1,5]
[1,2] [1,2]
[1,7] [1,7]
[1,6] [1,6]
[5,1] [5,1]
[5,5] [5,5]
[5,2] [5,2]
[5,7] [5,7]
[5,6] [5,6]
[7,1] [7,1]
[7,5] [7,5]
[7,2] [7,2]
[7,7] [7,7]
[7,6] [7,6]
- 这是为什么呢?
- 如何避免这种情况?
- 如何让多个独立的迭代器指向范围的不同位置?
- Should I implement a cartesian product in a different way? (that's my previous question)
虽然它没有反映在上面的 MCVE 中,但请考虑一个用例,其中有人尝试实现类似于 std::max_element 的东西 - 尝试将迭代器返回到叉积中的最高值对。在寻找最高值时,您需要将迭代器存储到当前最佳候选者。它在您搜索时无法更改,如果您需要范围的副本(如其中一个答案中所建议),则管理迭代器会很麻烦。
实体化整个叉积也不是一种选择,因为它需要大量内存。毕竟,使用具有过滤器和其他即时转换的范围的全部目的是避免这种实现。
【问题讨论】:
-
range是一个代理对象,主要被认为是在遍历时进行延迟评估。如果您想多次遍历范围,最好先将其转移到容器中。 -
@metalfox 我不介意在必要时多次重新评估东西,但是将交叉产品具体化到容器中 - 这将不必要地占用大量内存。