[C++-sig] Iterators for heterogeneous container

Thomas Daniel thomasd57 at yahoo.com
Sat Nov 7 23:25:41 CET 2009



troy d. straszheim wrote:
> Thomas Daniel wrote:
>>
>> BOOST_PYTHON_MODULE(vegetables)
>> {
>>    class_<Garden>("Garden")
>>        .def("get_potatoes", &Garden::get_potatoes)
>>        .def("get_tomatoes", &Garden::get_tomatoes)
>>    ;
>>    class_<TomatoIter>("TomatoIter")
>>        .def("__iter__", &TomatoIter::get_next)
>>    ;
>> }
>>
>> That at least compiles - unlike all my previous attempts that 
>> generate three pages of template errors - but python complain:
>>
>> TypeError: iter() returned non-iterator of type 'Tomato'
>>
>> so now I am trying to figure out how to tell boost that get_tomatoes 
>> returns an iterator ...
>>
>
> Please don't top-post, guys
>
> As you know, python iterators have a function next() that returns the 
> next object in the iteree, or throw StopIteration when they're at the 
> end.  As you also know, python expects member functions __iter__() to 
> return an iterator.  Is the thing returned by TomatoIter::get_next an 
> iterator, ie does it implement the iterator interface?
>
> -t
>
>
Thank you very much for the email, you did put me on the right track and 
I finally figured out how to do it, with help from here also: 
http://wiki.python.org/moin/boost.python/iterator

The solution involves creating a wrapper class around get_next(), which 
throws StopIteration when done and a "pass_through" function to bind to 
__iter__:

inline TomatoIter pass_through(const TomatoIter& iter) { return iter; }

Tomato next(TomatoIter& iter) {
    Tomato tomato = iter.get_next();
    if (!tomato) {
        PyErr_SetString(PyExc_StopIteration, "No more data.");
        throw_error_already_set();
    }
    return tomato;
}

Now, I can do this:
BOOST_PYTHON_MODULE(Garden)
{  
     ......
    class_<TomatoIter>("TomatoIter", no_init)
        .def("next", next)
        .def("__iter__", pass_through)
    ;

and it works.

Thomas



More information about the Cplusplus-sig mailing list