求实现C++20返回底层范围迭代器的range适配器iterator_range
实现
iterator_range 范围适配器 要实现你需要的范围适配器,让范围迭代时产出元素迭代器而非元素本身,我们可以基于C++20的Ranges库构建自定义视图,以下是完整实现方案:
1. 定义迭代器视图类型
这个视图会包装输入范围,重写迭代逻辑,让每次迭代返回原范围的迭代器:
#include <ranges> #include <iterator> template<std::ranges::input_range Range> class iterator_view : public std::ranges::view_interface<iterator_view<Range>> { private: Range m_range; public: iterator_view() = default; constexpr explicit iterator_view(Range r) : m_range(std::move(r)) {} // 自定义迭代器:产出原范围的迭代器 struct iterator { using iterator_type = std::ranges::iterator_t<Range>; iterator_type current; constexpr iterator(iterator_type it) : current(std::move(it)) {} constexpr iterator_type operator*() const { return current; } constexpr iterator& operator++() { ++current; return *this; } constexpr iterator operator++(int) { auto tmp = *this; ++current; return tmp; } constexpr bool operator==(const iterator& other) const = default; }; // 非const范围的begin/end constexpr iterator begin() { return iterator(std::ranges::begin(m_range)); } constexpr iterator end() { return iterator(std::ranges::end(m_range)); } // const范围的begin/end(适配只读场景) constexpr iterator begin() const requires std::ranges::input_range<const Range> { return iterator(std::ranges::begin(m_range)); } constexpr iterator end() const requires std::ranges::input_range<const Range> { return iterator(std::ranges::end(m_range)); } };
2. 定义管道适配接口
通过lambda实现适配器,支持管道符|直接调用:
// 全局适配器对象,支持管道语法 inline constexpr auto iterator_range = []<std::ranges::input_range Range>(Range&& r) { return iterator_view<std::views::all_t<Range>>(std::forward<Range>(r)); };
3. 使用示例
完全匹配你给出的写法,效果等价于标准for循环:
#include <vector> int main() { std::vector<int> range{0,1,2,3}; // 迭代获取元素迭代器 for(std::vector<int>::iterator vit : range | iterator_range) { int v = *vit; // 此处可直接操作迭代器,比如获取元素地址、判断是否为末尾等 } // 支持const范围的场景 const std::vector<int> const_range{4,5,6}; for(auto cit : const_range | iterator_range) { int v = *cit; } }
关键细节说明
- 依赖C++20及以上标准的Ranges库,主流编译器(GCC 10+、Clang 13+、MSVC 2022+)均支持。
iterator_view继承自view_interface,自动获得empty()、size()(若原范围支持)等默认范围操作。- 适配器通过
std::views::all_t处理左值/右值范围,保证原范围的生命周期安全。 - 自定义迭代器的
operator*直接返回原范围的迭代器,完全匹配你需要的等价效果。
内容的提问来源于stack exchange,提问作者bradgonesurfing
相关产品推荐
相关产品推荐

