12

我想知道如何在 C++ 中实现生成器,比如 Python?Python 可以使用关键字“yield”来做到这一点。但是如何在 C++ 中做到这一点?

4

6 回答 6

11

在 C++ 中,我们有“迭代器”。一个明确地要求一个interator,明确地增加它并取消引用它。

如果您希望它们与标准库函数一起使用,它们应该主要从 派生std::forward_iterator,并实现一些它的函数。

另一种在集合上模拟生成器的方法是允许一个函数作为成员函数的参数,该函数将其所有值提供(生成)给该函数:

struct MyCollection {
    int values[30];

    template< typename F >  
    void generate( F& yield_function ) const {
       int* end = values+30; // make this better in your own code :)
       for( auto i: values ) yield_function( *i );
    }
};

// usage:
c.generate([](int i){ std::cout << i << std::endl; });

// or pre-C++11:
struct MyFunction { 
    void operator() (int i)const { printf( "%d\n", i); }
};
MyCollection c;
c.generate( MyFunction() );
于 2009-09-07T11:12:18.773 回答
8

这……先生们……是纯黑魔法:

http://www.codeproject.com/Articles/29524/Generators-in-C

我已经尝试过了,它甚至可以递归地工作。从那以后我就经常使用它。生成器,几乎是 C++ 中的一等公民。甚至没有任何性能开销。

向作者致以最诚挚的敬意

于 2012-02-03T23:56:05.580 回答
6

详细说明迭代器的实现:这是一个例子。它可以用作循环变量,也可以用于标准算法。

#include <iterator>

template< typename T, typename TDiff = T >
struct TGenerator : public std::iterator<std::forward_iterator_tag,T,TDiff> {
  T from,to;
  T value;
  TDiff step;
  bool issentinel;

  TGenerator( T from, T to, TDiff step, bool sentinel = false )
    : from(from),to(to),step(step),issentinel(sentinel), value(from)
  {}

  void operator++(){ value += step; }

  const T& operator*()const { return value; }

  bool operator!=( const TGenerator& other ) const {
    return value<to;
  }

  TGenerator sentinel()const { return TGenerator(0,0,0,true); }

};


#include <algorithm>
#include <iostream>

int main()
{
  TGenerator<int> i(0,10,3);
  std::copy( i, i.sentinel(), std::ostream_iterator<int>( std::cout, " " ) );

    return 0;
}
于 2009-09-07T11:37:00.580 回答
6

You can't do it, really, but you can fake it. Here's a way you can fake it in C, which you can use in C++ as well.

于 2009-09-07T10:38:58.710 回答
1

多次调用协程并得到不同的答案意味着您保持某种状态。保持状态的方法是对象。使它们看起来像函数调用的方法是运算符重载。请参阅http://en.wikipedia.org/wiki/Function_object

于 2009-09-07T11:10:19.823 回答
1

您可以使用boost.context(抱歉,还没有在 boost 发行版中,您必须从boost vault获取它)。

一个典型的示例代码是这样的:

#include <iostream>
#include <boost/context.hpp>

using namespace std;

struct Parameters {
  int par1;
  float par2;
};

boost::context c1;
boost::context c2;

void F(void* parameters) {
  Parameters& pars = *(Parameters*)parameters;
  cout << pars.par1 << endl;
  c2.jump_to(c1);
  cout << pars.par2 << endl;
};

int main() {
  c1 = boost::context::current();
  Parameters p;
  p.par1 = 8;
  c2 = boost::context::create_context( F , c1 , p );
  c1.jump_to(c2);
  p.par2 = 1.3;
  c1.jump_to(c2);
}
于 2010-11-24T16:42:42.623 回答