一个range 风格的范围迭代器封装实现

一个range 风格的范围迭代器封装实现


go 里面有个range 的表达式可以遍历很多容器,最近应该是1.21支持range int,这看起来很像 python的 range 了,很舒服,想着很久没用cpp 写东西了就准备按照迭代器整一个,做小点,也不用什么模板;

第一种宏定义

这种其实类似 哪些OIer 常用的 for_each 宏

1
    #define rangeI(_I, _end) for (i = 0; i < (_end); i++)

其实就是一个包装常见的 for 表达式头的一个宏,限制挺多,优点是几乎零开销;

迭代器类封装实现

这个东西实现上并未考虑太多性能,应该会需要创建两个对象,这个有点像cpp 20里面增加的,ranges::itoa_views();但是这个功能更单一,仅用于整型范围迭代,而且接口也是更使用,提供,start,end,step,支持for range双向遍历

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63


class RangeIter {
  private:
  int step;
  int cur_val;

  public:
  RangeIter(int step, int val) : step(step), cur_val(val) {}

  // these three methods form the basis of an iterator for use with a rangeIter-based for loop
  bool operator!=(const RangeIter &other) const {
    if (step < 0) {
      return cur_val != other.cur_val && cur_val > other.cur_val;
    }
    return cur_val != other.cur_val && cur_val < other.cur_val;
  }

  // this method must be defined after the definition of IntVector since it needs to use it
  int operator*() const { return cur_val; }
  const RangeIter &operator++() {
    cur_val += step;
    return *this;
  }
};
class Range {
  private:
  int _st, _end, _step;
  bool args_check() const {
    if (_step == 0) {
      return false;
    }
    if (_step < 0 && _st <= _end) {
      return false;
    }
    return _step <= 0 || _st < _end;
  }

  public:
  Range(int start, int end, int step) : _st(start), _end(end), _step(step) {}
  Range(int start, int end) : _st(start), _end(end), _step(1) {}
  explicit Range(int end) : _st(0), _end(end), _step(1) {}
  RangeIter iter() { return RangeIter{_step, _st}; }
  RangeIter cbegin() const {
    if (!args_check()) {
      throw std::invalid_argument("step should match the exper start+n*step>end");
    }
    return RangeIter{_step, _st};
  }
  RangeIter cend() const {
    // if (!args_check()){
    //     throw std::invalid_argument("step should match the exper start+n*step>end");
    // }
    return RangeIter{_step, _end};
  }
  RangeIter begin() {
    if (!args_check()) {
      throw std::invalid_argument("step should match the exper start+n*step>end");
    }
    return RangeIter{_step, _st};
  }
  RangeIter end() { return RangeIter{_step, _end}; }
};

这里对 begin 做了参数检查,避免意外的错误情况,导致无限循环之类的情况,其实正常情况应该是把RangeIter 这个迭代器实现给塞到 private 域里面去,避免他人骚操作;但这里只是一个简单的演示demo就不用考虑太多;

调用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
int main() {
  std::vector<int> val{1, 2, 3};
  int i = 0;
  rangeI(i, val.size()) { std::cout << val[i] << std::endl; }
  // 1
  // 2
  // 3
  try {
    for (auto i : Range(static_cast<int>(val.size()), 0, -1)) {
      std::cout << i << ";\n";
    }
  } catch (std::logic_error &e) {
    std::cout << "error" << e.what() << std::endl;
  }
  // 3;
  // 2;
  // 1;
  std::cout << std::endl;
}

总之复习了for range和迭代器实现

Licensed under CC BY-NC-SA 4.0
往日已经不在,未来尚未开始
使用 Hugo 构建
主题 StackJimmy 设计