c++ - 等效于 C++ 到 Python 生成器模式

标签 c++ python generator yield coroutine

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

python

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

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

目标是维护上述序列的两个实例,并以半锁步方式迭代它们,但以 block 为单位。在下面的示例中,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++ 中的解决方案,我唯一能找到的就是用 C++ 协程模拟 yield,但我还没有找到关于如何执行此操作的任何好的引用。我也对这个问题的替代(非通用)解决方案感兴趣。我没有足够的内存预算来保留遍历之间的序列拷贝。

最佳答案

生成器存在于 C++ 中,只是以另一个名称存在:输入迭代器。例如,从 std::cin 读取类似于拥有 char 的生成器。

您只需要了解生成器的作用即可:

  • 有一个数据 block :局部变量定义了一个状态
  • 有一个初始化方法
  • 有一个“下一步”的方法
  • 有一种方法可以发出终止信号

在您的简单示例中,这很简单。概念上:

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++ 有点冗长 :)

关于c++ - 等效于 C++ 到 Python 生成器模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53575534/

相关文章:

c++ - DirectX11 ReportLiveObjects 实例化

c++ - 双端队列问题和索引运算符超出双端队列大小

c++ - 为什么 C++11 允许将局部变量声明为 thread_local?

Python 排序顺序 unicode/ansi 不同

c++ - 不能在 C++ 项目中使用 openmp

用于 Windows 的 python whois

python - 将小部件添加到 qtablewidget pyqt

python - Python 是否允许递归 __iter__ 函数?

javascript - 更好地理解 javascript 的产量

ruby-on-rails - 如何从代码中调用生成器?