I want to know how to implement a generator , like python , in C++? In python, it can use keyword "yield" to do so. But how to do it in C++?
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.
Calling a coroutine multiple times and getting different answers means you keep some state. The way to keep a state is objects. The way to make them look like function call is operator overloading. See http://en.wikipedia.org/wiki/Function_object.
In C++ we have 'iterators'. One explicitly asks for an interator, explicitly increments it and dereferences it.
If you want them to be used with the standard library functions, they should mostly be derived from std::forward_iterator
, and implement a number of it's functions.
An other way to mimic kindof a generator on a collection is allowing a function as argument to a member function that feeds (yields) all of it's values to that function:
struct MyCollection {
int values[30];
template< typename F >
void generate( F& functor ) const {
int* end = values+30; // make this better in your own code :)
for( int* i = values; i != end; ++i ) functor.accept( *i );
}
};
struct MyFunction { void accept(int i)const { printf( "%d\n", i); } };
MyCollection c;
c.generate( MyFunction() );
To elaborate on the iterator implementation: this is an example. It can be used as a loop variable, or in std algorithms.
#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, T 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;
}