gpt4 book ai didi

c++ - 复杂范围的多个迭代器

转载 作者:行者123 更新时间:2023-12-02 15:52:30 25 4
gpt4 key购买 nike

我正在尝试使用多个迭代器来实现更复杂的范围(使用 range-v3 库)——使用 filterfor_each产量。然而,当我尝试将多个迭代器保持在这样的范围内时,它们共享一个共同的值。例如:

#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]
<小时/>

虽然它没有反射(reflect)在上面的 MCVE 中,但请考虑一个用例,其中有人尝试实现类似于 std::max_element 的东西 - 尝试将迭代器返回到中最高值对叉积。在寻找最高值时,您需要将迭代器存储到当前最佳候选者。当您搜索时它不能改变,并且如果您需要该范围的拷贝(如其中一个答案中所建议的),那么管理迭代器会很麻烦。

具体化整个叉积也不是一种选择,因为它需要大量内存。毕竟,使用带有过滤器和其他即时转换的范围的全部目的是避免这种具体化。

最佳答案

结果 View 存储的状态似乎是单 channel 的。您可以通过简单地根据需要制作尽可能多的 View 拷贝来解决这个问题:

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 range1= range; // Copy the view adaptor
auto it1 = range1.begin();

for (auto it2 = range.begin(); it2 != range.end(); ++it2) {
std::cout << "[" << it1->first << "," << it1->second << "] [" << it2->first << "," << it2->second << "]\n";
}

std::cout << '\n';
for (; it1 != range1.end(); ++it1) { // Consume the copied view
std::cout << "[" << it1->first << "," << it1->second << "]\n";
}
return 0;
}

另一种选择是将 View 具体化到容器中,如评论中所述。

<小时/>

记住上述单 channel View 的限制,实现 max_element 并不难返回迭代器的函数,其重要缺点是必须计算序列一次半。

这是一个可能的实现:

template <typename InputRange,typename BinaryPred = std::greater<>>
auto my_max_element(InputRange &range1,BinaryPred &&pred = {}) -> decltype(range1.begin()) {
auto range2 = range1;
auto it1 = range1.begin();
std::ptrdiff_t pos = 0L;

for (auto it2 = range2.begin(); it2 != range2.end(); ++it2) {
if (pred(*it2,*it1)) {
ranges::advance(it1,pos); // Computing again the sequence as the iterator advances!
pos = 0L;
}
++pos;
}
return it1;
}

关于c++ - 复杂范围的多个迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54047133/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com