[C++-sig] Re: Re: custom iterator object

Mike Rovner mike at bindkey.com
Fri Nov 8 19:53:07 CET 2002

"David Abrahams" <dave at boost-consulting.com> wrote in message
news:uy9853yrt.fsf at boost-consulting.com...
> "Mike Rovner" <mike at bindkey.com> writes:
> >> > I have the following class, implementing my iterator protocol:
> >> >
> >> > template<class T>
> >> > class Iter
> >> > {
> >> >     T* First();
> >> >     T* Next();
> >> > }
> >> > returning 0, when iteration is done.
> >> >
> >> Boost.Python provides several ways to wrap regular C++ iterators as
> >> Python iterators. Did you consider using those?
> >
> > Sure I did, but couldn't figure out how to do it ;)
> > IMHO it's NOT a regular iterator because operations '*' and '++' are
> > combined into 'Next'.
> No, of course it's not. However, you could consider making a C++
> iterator using, say, the Boost Iterator Adaptors library, and then
> wrapping that. Maybe that's too much work, though.
> >> > I'm trying to wrap it to Python iterator protocol:
> >> What's "not good" about it?
> >
> > I have problems with return value. In __iter__ I have to return
> > self, but there is no Python self yet in wrapping class.  So
> > probably I have to duplicate part of the BPL iterator guts, but I
> > got lost :(
> I'm lost, too. You haven't shown enough of what you're trying to do
> for me to be able to help. Please try showing the code you hope to use
> to wrap this stuff, and add lots of comments to describe what's
> happening.

So I have custom iterator 'Iter' as shown above. It's like Python iterator,
so I tend to use it instead of wrapping in iterator.
Now I have a class:

class Scheme {
  Iter A();
  Iter B();
  Iter C();

which I want to exposure. So I write:

    .def("__iter__",  ???(&Scheme::A))
    .add_property("b", ???(&Scheme::B))
    .add_property("c", ??(&Scheme::C))

to pretend objects itself acts as iterator A, b and c as B and C. But I have
trouble in places ???.
I need a Python iterator object there like 'iterator' or 'range' functions
return, but first I need to instantiate Iter with A|B|C member parameter to
create a custom iterator.

I can wrap an Iter as

typedef Iter (*GetIterFunc)();
template<class T>
struct PyIter
  PyIter(GetLrIterFunc const get_func) : started(false), it(get_func()) {}
  const T* begin()  {return it.First();}
  const T* end()    {return 0;}
  const T* operator++() {return v=it.Next();}
  const T  operator*()  {return *v;}
  bool started;
  T* v;
  Iter it;

  class_<PyIter>("PyIter", init<GetIterFunc>())
    .def("__iter__", range(&PyIter::begin, &PyIter::end))

but I still don't know how to instantiate it.

More information about the Cplusplus-sig mailing list