c++ - 使用惰性迭代器的 C++ 过滤
问题描述
template<typename Iterator>
struct Range {
using LazyIterator = Iterator; // required for accessing the used Iterator type from other locations
Iterator m_begin;
Iterator m_end;
auto begin() { return m_begin; }
auto end() { return m_end; }
};
template<typename Iterator>
Range(Iterator, Iterator) -> Range<Iterator>;
template<typename Iterator, typename Callable>
struct FilteringIterator : Iterator {
Callable callable;
using OriginalIterator = Iterator;
using t = typename OriginalIterator::value_type;
FilteringIterator(const Iterator begin, Callable callable):Iterator(begin),callable(callable){}
Iterator &get_orig_iter() { return ((Iterator &)*this); }
auto operator*() { return callable(*get_orig_iter()); }
};
auto filter = [](auto action) {
return [=]( auto &container) {
using Container = std::decay_t<decltype(container)>;
using Iterator = typename Container::iterator;
using actiontype = decltype(action);
using filter_iterator = FilteringIterator<Iterator, actiontype>;
return Range{filter_iterator{container.begin(),action}, filter_iterator{container.end(),action}};
};
};
我需要一个惰性迭代器,它将遍历一个范围并惰性过滤它。例如
auto v = std::vector<double>{};
auto odd_gen = views::odds();
for(int i=0; i<5; ++i)
v.push_back(odd_gen() * 2.5);
// v contains {2.5, 7.5, 12.5, 17.5, 22.5} here
new_line();
for(auto a : v | filter(greater_than(15))) // filter is applied lazily as the range is traversed
std::cout << a << std::endl;
// print { 17.5, 22.5} here
但它打印
{0,0,0,0,17.5,22.5}
我希望它只打印 17.5、22.5
我怎样才能做到这一点?
解决方案
您的代码从不跳过元素,它只是转换它们。您需要确保在operator*()
调用 时,它首先在callable
返回时推进迭代器false
,然后才返回 所指向的值Iterator
。
尽管您必须照顾好一些极端情况。如果输入以与过滤器不匹配的元素结尾,那么您就会遇到问题。operator++()
您还需要在调用时跳过所有过滤掉的元素。还要考虑过滤器不匹配输入的任何元素的情况;在这种情况下,您必须确保begin()
等于end()
。
推荐阅读
- powershell - PowerShell 获取浏览器选项卡的 URL
- javascript - 读取文件然后在客户端显示
- xtext - 如何控制从现有 Ecore 到 Xtext 的生成过程?
- r - 在 mlr3 中进行基准测试时 R 会话崩溃
- reactjs - 登录后未使用 Fetch 存储的 Cookie
- spring-boot - 在编译时验证 application.yml 中的属性名称
- wordpress - 如何更新在 GCP 上的托管实例组上运行的 Wordpress 网站
- amazon-web-services - 是否有一种简单的配置可以在 S3 对象未使用一段时间后永久删除它们?
- arrays - perl 根据值创建多个数组并循环遍历它们
- android - 如何在不推荐使用 onActivityResult 的情况下使用 Facebook 登录 CallbackManager?