re C ++范围迭代器:只有一个类是不是很糟糕?

时间:2013-02-04 07:32:51

标签: c++ iterator

e.g。应将以下课程分为两部分:

class Range {
 public:
  Range(int end);

  Range begin();
  Range end();

  // Second class would contain these methods.
  bool operator!=(const Range& range);
  int operator*();
  void operator++();
};

// Print 012
// Almost as pretty as Python :D
for (int i : Range(3)) {
  std::cout << i;
}

PS:标准库中是否有这样的类?

更新

以下是替代设计的样子:

class Range;

class RangeIterator {
 public:
  bool operator!=(const RangeIterator& range_iterator);
  int operator*();
  void operator++();

 private:
  RangeIterator(const Range& range);
};

class Range {
 public:
  Range(int end);

  RangeIterator begin();
  RangeIterator end();

  friend class RangeIterator;
};

3 个答案:

答案 0 :(得分:2)

我个人将它分开--C ++中的类型安全点是编译器在你将一个范围传递给一个应该采用迭代器的函数时反过来,反之亦然。如果同一个类同时执行这两个角色,那么您将失去这个角色,如果myrangemyrange.begin()具有相同的类型,则会产生实际错误。也就是说,既然你也喜欢Python,你可能不会认为这很重要,你已经习惯了__iter__返回self的对象。从C ++ POV我会说这可能看起来有点不寻常/棘手/聪明。

但这并不意味着必须在您的界面中公开定义RangeIterator。您可以使用typedef Range::iterator_type,由私有嵌套类或命名空间中定义的类支持。无论哪种方式,有人可以检查头文件中的类定义,但你不会记录任何超出“它可以通过名称Range::iterator_type引用,并且这是你可以用它做什么”。

说到这一点,RangeRangeIterator目前都不满足迭代器要求。如果您决定希望Iterator成为迭代器,那么您需要专门化std::iterator_traits,添加一些typedef或({common})派生自std::iterator。无论你采用哪种方式,都要包含更多样板。这可能会影响您的决定。您开始编写的内容越多,定义额外类的成本就越低。

这里RangeIterator变成了迭代器:

class RangeIterator : public std::iterator<std::input_iterator_tag, int> {
 public:
  bool operator!=(const RangeIterator& range_iterator) const;
  bool operator==(const RangeIterator& range_iterator) const;
  int operator*() const;
  RangeIterator &operator++();
  RangeIterator operator++(int);

 private:
  RangeIterator(const Range& range);
};

答案 1 :(得分:0)

是否应将其拆分为两个类取决于将使用该软件的上下文。

例如,如果软件的其余部分与此类代码无关,则可能有意义,并降低复杂性,将事物保持在一起。另一方面,如果您正在努力使用某种通用实用程序,那么可能的可维护性(或可以说是为了简单起见)可以更好地分解。

我觉得你应该考虑可维护性和可读性,而不是对这样的代码片段有一个硬性规则。从长远来看,您的设计选择是否会使维护更容易?它会降低项目的复杂性吗?

这是构建软件的一个很酷的事情!

答案 2 :(得分:0)

我会简单地坚持使用第二种方法,它有一些好处:

  1. 您可能希望以不同的方式遍历Range,具体取决于具体内容 你想完成。但你可能不想膨胀 Range接口与不同遍历的操作,即使你 可以预见到你需要的那些。

  2. 将遍历机制与Range对象分开让我们 为不同的遍历策略定义迭代器 在Range界面中枚举它们。例如, FilteringRangeIterator可能只提供对这些元素的访问权限 满足特定的过滤约束。

  3. 您可能希望为Range提供多态性,然后您可以 概括迭代器概念以支持多态迭代。