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

David Abrahams dave at boost-consulting.com
Sun Nov 10 05:30:34 CET 2002


"Mike Rovner" <mike at bindkey.com> writes:

> "David Abrahams" <dave at boost-consulting.com> wrote in message
> news:uy9853yrt.fsf at boost-consulting.com...
>> "Mike Rovner" <mike at bindkey.com> writes:

> 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:
>
> BOOST_PYTHON_MODULE(Py1)
> {
>   class_<Scheme>("Scheme")
>     .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;}
> private:
>   bool started;
>   T* v;
>   Iter it;
> };
>
>   class_<PyIter>("PyIter", init<GetIterFunc>())

OK, there's no point in bothering with the init<...> declaration
there. You might as well use no_init, since you're not going to
construct these from Python and Boost.Python doesn't have a way to
convert any Python objects to C++ function pointers.

>     .def("__iter__", range(&PyIter::begin, &PyIter::end))

Well, you can't use range(...) here; that's intended for real C++
iterators, and you don't have any (PyIter doesn't conform). 

Here's my suggestion:

  Try doing what you need to do in Pure Python. Build a little
  new-style class (derived from object) called Scheme, and add the
  iterator interface you want to see. To do that, you may find
  yourself building some little Python iterator classes.

  Now, when you have all that working, translate your Python iterator
  classes into C++, and wrap them with Boost.Python. Remember that the
  iterator's own __iter__ method can be implemented by wrapping this
  C++ function:

    object identity(object x)  { return x; }

HTH,
-- 
                       David Abrahams
   dave at boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution





More information about the Cplusplus-sig mailing list