在C++中实现Python的range
代码在最后,可以先看代码再看说明
在实现过程中几个应该注意的问题
整型溢出
for (auto i : irange(1e9, -2e9, -2e9))
std::cout << i << "\n";
std::cout << '\n';
// 如果不注意溢出,会发生如下输出
1000000000
-1000000000
1294967296
-705032704
1589934592
-410065408
1884901888
-115098112
使用<limits>
中的整型范围可解,同时std::numeric_limits
可以得出泛型的范围
std::numeric_limits<value_type>::max(); // 最大值
std::numeric_limits<value_type>::min(); // 最小值
std::numeric_limits<value_type>::lowest(); // 最小值
对于整型来说,min(), lowest()
是相同的
对于浮点数,min()
代表正区间的下溢值,lowest()
代表最小值(在负区间)
如下,可以使i
不溢出
if (i <= std::numeric_limits<value_type>::max() - step)
i += step;
else
i = std::numeric_limits<value_type>::max();
迭代器选择
众所周知,C++中for (<type> <name> : <iterable>) {}
是通过begin(), end()
等函数获得的迭代器运作的。C++提供了多种迭代器类型,如ForwardIterator,RandomAccessIterator等,需要选择合适的range的迭代器
我选择InputIterator作为迭代器类型,提供了只读、只递增的限制
template <typename T, typename Diff>
class RangeIterator
{
public:
typedef std::input_iterator_tag iterator_category;
typedef T value_type;
typedef const T *pointer;
typedef const T &reference;
typedef Diff difference_type;
}
注意iterator_category, value_type, pointer, reference, difference_type
都要有,否则无法被识别为InputIterator!
理论上,begin()
应该是变动的,但end()
不应该是变动的,可以在返回值加上限制(const)
iterator begin() const {
return iterator(start_, step_); }
const iterator end() const {
return iterator(stop_