赞
踩
以前我们只能这样来遍历容器或者数组
vector<int> arr {1,2,3,4,5};
for(auto it =arr.begin(); it!=arr.end(); it++
{
}
或者是
for_each(auto it=arr.begin(); it!=arr.end(); do_something);
这两种方法的弊端在于,都要写begin,和end
新的基于范围的for循环是这样的
for(auto v:arr)
{
}
冒号前面的局部变量声明只要求能够支持容器类型的隐式转换。
这个for-range循环实际上只是C++的语法糖,它是下面代码的等价替换。
for(auto __begin = arr.begin(), __end = arr.end(); __begin!=__end; ++__begin
{}
也就是说只要for-range循环冒号后边的东西是个类,这个类只要实现begin(),end()方法,并且两个方法返回一个迭代器即可。迭代器正常要实现 !=重载,++重载 和 *重载。
现在我们要实现一个类似于Python的range循环
使用起来是这样
for(int i : range(2,5,2))
{
}
这个range是个函数,它返回一个我们前面说的类
我们要实现迭代器,满足要求的类,和range函数
代码如下:
#pragma once #include <iostream> namespace detial_range { template <typename T> class iterator { public: using value_type = T; using size_type = size_t; private: //Q:为什么迭代次是size_type,迭代步长和起始迭代值是value_type //A:因为cursor_代表要迭代的次数,其肯定是正整数,但是迭代步长和迭代值则是根据我们想要迭代什么数据类型来的。 size_type cursor_; //迭代次数 const value_type step_; //迭代步长 value_type value_; //起始迭代值 public: iterator(size_type cur_start, value_type begin_value, value_type step_value) : cursor_(cur_start), value_(begin_value), step_(step_value) { value_ += (step_ * cursor_); } value_type operator*() const { return value_; }; bool operator!=(const iterator& rhs) { return (cursor_ != rhs.cursor_); } iterator& operator++(void) { value_ += step_; ++cursor_; return (*this); } }; //range类的具体实现 template<typename T> class impl { public: using value_type = T; using reference = const value_type&; using const_reference = const value_type&; using iterator = const detial_range::iterator<value_type>; using const_iterator = const detial_range::iterator<value_type>; using size_type = typename iterator::size_type; private: const value_type begin_; const value_type end_; const value_type step_; const size_type max_conut_;//要迭代的次数 //因为step_可能不是end_-begin_的最大公约数,所以需要调整迭代次数 size_type get_adjust_conut(void) const { if (step_ > 0 && begin_ >= end_) throw std::logic_error("end_ 必须大于 begin_"); else if (step_ < 0 && begin_ <= end_) throw std::logic_error("end_ 必须小于 begin_"); size_type x = static_cast<size_type> ((end_ - begin_) / step_); if ((begin_ + step_ * x) != end_)++x; return x; } public: //外部接口 impl(value_type begin_value, value_type end_value, value_type step_value) :begin_(begin_value), end_(end_value), step_(step_value), max_conut_(get_adjust_conut()) {} size_type size() const { return max_conut_; } const_iterator begin() const { return { 0,begin_, step_ }; } const_iterator end() const { return const_iterator{ max_conut_, begin_, step_ }; } }; //range的外敷函数模板 template<typename T> detial_range::impl<T> range(T end) { return { {},end,1 }; } template<typename T> detial_range::impl<T> range(T begin, T end) { return { begin, end, 1 }; } template <typename T, typename U> auto range(T begin, T end, U step) -> detial_range::impl<decltype (begin + step)> { using r_t = detial_range::impl<decltype(begin + step)>; return r_t{ begin ,end,step }; } }; void main() { for (int i : detial_range::range(2, 5,2)) { std::cout << "range(2,5) i:" << i << std::endl; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。