小编典典

与Python生成器模式等效的C ++

python

我有一些需要在C++中模仿的示例Python代码。我不需要任何特定的解决方案(例如基于协同例程的收益解决方案,尽管它们也是可接受的答案),我只需要以某种方式重现语义即可。

python

这是一个基本的序列生成器,显然太大了,无法存储实例化版本。

def pair_sequence():
    for i in range(2**32):
        for j in range(2**32):
            yield (i, j)

目标是维护上述序列的两个实例,并以半锁步的方式在块上进行迭代。在下面的示例中,first_pass使用对的序列来初始化缓冲区,然后second_pass重新生成
相同的精确序列 并再次处理缓冲区。

def run():
    seq1 = pair_sequence()
    seq2 = pair_sequence()

    buffer = [0] * 1000
    first_pass(seq1, buffer)
    second_pass(seq2, buffer)
    ... repeat ...

C ++

对于C 解决方案,我唯一能找到的就是模仿yieldC
协程,但是我还没有找到有关如何执行此操作的良好参考。我也对这个问题的替代(非一般)解决方案感兴趣。我没有足够的内存预算来保留两次通过之间的序列副本。


阅读 221

收藏
2020-12-20

共1个答案

小编典典

生成器在C ++中存在,只是另一个名称: Input Iterators 。例如,从读取std::cin类似于使用的生成器char

您只需要了解生成器的功能:

  • 有大量数据:局部变量定义 状态
  • 有一个初始化方法
  • 有一个“下一个”方法
  • 有一种信号终止的方法

在您的琐碎示例中,这很容易。从概念上讲:

struct State { unsigned i, j; };

State make();

void next(State&);

bool isDone(State const&);

当然,我们将其包装为适当的类:

class PairSequence:
    // (implicit aliases)
    public std::iterator<
        std::input_iterator_tag,
        std::pair<unsigned, unsigned>
    >
{
  // C++03
  typedef void (PairSequence::*BoolLike)();
  void non_comparable();
public:
  // C++11 (explicit aliases)
  using iterator_category = std::input_iterator_tag;
  using value_type = std::pair<unsigned, unsigned>;
  using reference = value_type const&;
  using pointer = value_type const*;
  using difference_type = ptrdiff_t;

  // C++03 (explicit aliases)
  typedef std::input_iterator_tag iterator_category;
  typedef std::pair<unsigned, unsigned> value_type;
  typedef value_type const& reference;
  typedef value_type const* pointer;
  typedef ptrdiff_t difference_type;

  PairSequence(): done(false) {}

  // C++11
  explicit operator bool() const { return !done; }

  // C++03
  // Safe Bool idiom
  operator BoolLike() const {
    return done ? 0 : &PairSequence::non_comparable;
  }

  reference operator*() const { return ij; }
  pointer operator->() const { return &ij; }

  PairSequence& operator++() {
    static unsigned const Max = std::numeric_limts<unsigned>::max();

    assert(!done);

    if (ij.second != Max) { ++ij.second; return *this; }
    if (ij.first != Max) { ij.second = 0; ++ij.first; return *this; }

    done = true;
    return *this;
  }

  PairSequence operator++(int) {
    PairSequence const tmp(*this);
    ++*this;
    return tmp;
  }

private:
  bool done;
  value_type ij;
};

所以,嗯…可能是C ++有点冗长:)

2020-12-20