[C++-sig] Boost iterators

David Abrahams david.abrahams at rcn.com
Thu Apr 25 21:29:11 CEST 2002


----- Original Message -----
From: "Martin Casado" <casado2 at llnl.gov>
To: "David Abrahams" <david.abrahams at rcn.com>
Cc: "pysig" <c++-sig at python.org>
Sent: Wednesday, April 24, 2002 6:00 PM
Subject: Re: Re: [C++-sig] Boost iterators


> > Rather than adding cruft to each function which returns a
vector<int>,
> > What I think you want is a def_iterator() function on class_<>. Then
you
> > just write:
> >
> >     .add(class_<std::vector<int> >("int_vector")
> >             .def_iterator())
>
> Dave,
>
>   I've had some more time to look into iterator support.  I've written
a
>   function template which accepts an stl container conforming type and
>   returns a PyIterator thingy like so..
>
>   template <typename T>
>   PyIter<vector<int> > foo(T& t)
>   {
>       return PyIter<vector<int> >(t.begin(),t.end());
>   }
>
>   I then simply add this to my class with def(..)
>
>     class_<vector<int> >("vector_int")
>        .def_init()
>        .def("__iter__",static_cast<PyIter<vector<int> >
> (*)(vector<int>&)>(foo)) >


I don't understand why you need the cast here; it seems as though
&foo<vector<int> > would do just as well.

>        .def("push_back",&vector<int>::push_back)
>
>   I've hacked class.hpp to add a .def_iterator() which does exactly
that
>   in the background so now all I have to do is:
>
>   class_<goo>("goo").def_iterator()

Cool!

>   This all seems to work fine however I do have a couple of concerns
>
>   1. The return value maintins references to the container's
iterators.
>   Is there a way to keep the container alive as long as the python
>   iterator object is alive?  Something like
return_internal_reference(),
>   but handles values which maintain internal references.

How about with_custodian_and_ward<0,1>() should handle it, right? You
want the self argument (argument 1) to stay alive as long as the return
value.

>
>   2. For each PyIter< > instance used, I have to create a class within
>   boost. Such as:
>
>   class_<PyIter<vector<int> > >
>
>   Would it be possible to do this on the fly, like during calls
>   to .def_iterator()?

Well, the Python object for the iterator type could be attached to the
class being defined, instead of the module, if that's what you mean.

    self& def_iterator()
    {
        class_<PyIter<T> > iter_class("iterator");

        // now the iterator class is stored in an attribute of the
container class
        Py_SetAttrString(this->object().get(), "iterator",
iter_class.object().get());

        ...
    }

-Dave







More information about the Cplusplus-sig mailing list