如何在C++中实现统一的过滤器迭代器?
实现带过滤功能的自定义迭代器
原代码的问题
- 错误地同时继承STL迭代器并维护独立的
iter成员,导致迭代器状态不一致,比如调用++时基类迭代器和成员iter的位置不同步。 - 构造函数未接收过滤函数对象,
func未初始化,运行时会触发未定义行为。 operator*的逻辑错误:只是在元素不符合条件时返回空格,而非跳过该元素,无法实现过滤遍历的需求。
正确实现方案
自定义过滤迭代器的核心是封装原迭代器,而非继承,同时在迭代过程中自动跳过不符合过滤规则的元素。需要实现迭代器的必要接口,包括关联类型、递增运算符、比较运算符以及解引用运算符。
完整实现代码
#include <iostream> #include <vector> #include <iterator> #include <functional> template <class Iter, class FilterFunction> class FilterIterator { public: // 定义迭代器关联类型,兼容STL迭代器要求 using iterator_category = typename std::iterator_traits<Iter>::iterator_category; using value_type = typename std::iterator_traits<Iter>::value_type; using difference_type = typename std::iterator_traits<Iter>::difference_type; using pointer = typename std::iterator_traits<Iter>::pointer; using reference = typename std::iterator_traits<Iter>::reference; // 构造函数:接收起始迭代器、结束迭代器、过滤函数 FilterIterator(Iter begin, Iter end, FilterFunction func) : current_(begin), end_(end), filter_(std::move(func)) { // 初始化时定位到第一个符合条件的元素 skip_invalid(); } // 前置递增运算符:跳过不符合条件的元素 FilterIterator& operator++() { ++current_; skip_invalid(); return *this; } // 后置递增运算符 FilterIterator operator++(int) { FilterIterator temp = *this; ++current_; skip_invalid(); return temp; } // 解引用运算符 reference operator*() const { return *current_; } // 指针访问运算符 pointer operator->() const { return &(*current_); } // 相等比较 bool operator==(const FilterIterator& other) const { return current_ == other.current_; } // 不等比较 bool operator!=(const FilterIterator& other) const { return !(*this == other); } private: Iter current_; Iter end_; FilterFunction filter_; // 跳过所有不符合过滤条件的元素 void skip_invalid() { while (current_ != end_ && !filter_(*current_)) { ++current_; } } }; // 辅助函数:简化FilterIterator的创建 template <class Iter, class FilterFunction> FilterIterator<Iter, FilterFunction> make_filter_iterator(Iter begin, Iter end, FilterFunction func) { return FilterIterator<Iter, FilterFunction>(begin, end, std::move(func)); } // 测试用的过滤函数对象:判断偶数 class IsEven { public: bool operator()(int num) const { return num % 2 == 0; } }; int main() { std::vector<int> vec = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // 创建过滤迭代器,只遍历偶数 auto begin = make_filter_iterator(vec.begin(), vec.end(), IsEven()); auto end = make_filter_iterator(vec.end(), vec.end(), IsEven()); for (auto iter = begin; iter != end; ++iter) { std::cout << *iter << std::endl; } // 也可以用lambda表达式作为过滤规则 std::cout << "\n过滤大于5的元素:" << std::endl; auto lambda_begin = make_filter_iterator(vec.begin(), vec.end(), [](int num) { return num > 5; }); auto lambda_end = make_filter_iterator(vec.end(), vec.end(), [](int num) { return num > 5; }); for (auto iter = lambda_begin; iter != lambda_end; ++iter) { std::cout << *iter << std::endl; } return 0; }
关键实现说明
- 迭代器关联类型:通过
std::iterator_traits获取原迭代器的类型信息,确保自定义迭代器兼容STL的迭代器范畴(比如随机访问、双向等)。 - 构造函数与初始化:构造时直接定位到第一个符合过滤条件的元素,避免第一次解引用时得到无效元素。
- 递增逻辑:每次递增后调用
skip_invalid()自动跳过不符合条件的元素,直到找到有效元素或到达容器末尾。 - 封装而非继承:避免了继承STL迭代器带来的状态不一致问题,同时适配所有类型的STL迭代器(包括指针类型的迭代器)。
- 辅助函数
make_filter_iterator:简化迭代器的创建,无需手动指定模板参数。
内容的提问来源于stack exchange,提问作者zrow
相关产品推荐
相关产品推荐

