我想知道如何在C中实现一个生成器,比如Python,Python可以使用关键字“yield”来实现。但是在C中如何实现呢?
inkz8wg91#
在C++中我们有“迭代器”。一个显式地请求一个迭代器,显式地递增它和取消引用它。如果您希望它们与标准库函数一起使用,那么它们大多数应该派生自std::forward_iterator,并实现它的许多函数。另一种模仿集合上生成器的方法是允许函数作为成员函数的参数,成员函数将其所有值提供给该函数:
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() );
ppcbkaq52#
这...先生们...是纯粹的黑魔法http://www.codeproject.com/Articles/29524/Generators-in-C我试过了,它甚至可以递归地工作。从那以后我就经常使用它。生成器,几乎是C++中的头等公民。甚至没有任何性能开销。带着我对作者最深的敬意
uelo1irk3#
你真的不能这么做,但是你可以假装它。这里是a way you can fake it in C,你也可以在C++中使用它。
h43kikqp4#
要详细说明迭代器实现:这是一个例子。2它可以作为一个循环变量,或者在标准算法中使用。
#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; }
lzfw57am5#
多次调用一个协程并得到不同的答案意味着你保留了一些状态。保留状态的方法是对象。使它们看起来像函数调用的方法是操作符重载。参见http://en.wikipedia.org/wiki/Function_object。
mepcadol6#
你可以使用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); }
6条答案
按热度按时间inkz8wg91#
在C++中我们有“迭代器”。一个显式地请求一个迭代器,显式地递增它和取消引用它。
如果您希望它们与标准库函数一起使用,那么它们大多数应该派生自
std::forward_iterator
,并实现它的许多函数。另一种模仿集合上生成器的方法是允许函数作为成员函数的参数,成员函数将其所有值提供给该函数:
ppcbkaq52#
这...先生们...是纯粹的黑魔法
http://www.codeproject.com/Articles/29524/Generators-in-C
我试过了,它甚至可以递归地工作。从那以后我就经常使用它。生成器,几乎是C++中的头等公民。甚至没有任何性能开销。
带着我对作者最深的敬意
uelo1irk3#
你真的不能这么做,但是你可以假装它。这里是a way you can fake it in C,你也可以在C++中使用它。
h43kikqp4#
要详细说明迭代器实现:这是一个例子。2它可以作为一个循环变量,或者在标准算法中使用。
lzfw57am5#
多次调用一个协程并得到不同的答案意味着你保留了一些状态。保留状态的方法是对象。使它们看起来像函数调用的方法是操作符重载。参见http://en.wikipedia.org/wiki/Function_object。
mepcadol6#
你可以使用boost.context(抱歉,还没有在boost发行版上,你必须从boost vault获得它)。
典型的示例代码如下所示: