[C++-sig] Re: iter(std::map<K*,V>)

David Abrahams dave at boost-consulting.com
Wed Jun 18 15:03:47 CEST 2003


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

> Hi all,
>
> I want to wrap a std::map container, which maps some pointer to wrapped
> class to another wrapped class.
>   typedef std::map<const Key*,Value> Map;
>
> In order to support 'for x in Map():' construct I need to implement
> __iter__.
> As I did for keys() call, I'd like to return ptr(it->first) as an iteration
> result.

OK...

> What is more simple (or recommended) way to do it?
>
> - Write and wrap helper iterator object with __iter__ and next methods like
>   struct Map_iter
>   {
>      Map_iter(const Map& m) : it(m.begin()), itend(m.end()) {}
>      Map_iter& identity(Map_iter& self) {return self;}
>      object next() {
>         if( it!=itend ) return ptr(it->first);
>         PyErr_SetString(PyExc_StopIteration,"");
>         throw_error_already_set();
>      }
>    private:
>      Map::const_iterator it, itend;
>   };
>   Map_iter get_iterator(const Map& m) { return Map_iter(m); }
>   and then
>   class_<Map_iter>("_iter")
>     .def("__iter__", &Map_iter::identity)
>     .def("next", &Map_iter::next)
>   ;
>   //... and in Map wrapper
>   .def("__iter__", get_iterator)
>
> or
> - Use iterator<>() with special return policy like
>   .def("__iter__", iterator<Map, return_value_policy<copy_map_key_ptr> >())

I guess whichever one is shorter.  The 2nd one looks pretty good.

> If later, I can't figure out the body of apply for my special return policy:
>
> struct copy_map_key_ptr
> {
>     template <class T>
>     struct apply
>     {
>         typedef to_python_value< ??? > type;
>     };
> };
>
> Any suggestions?

Well, to_python_value is the wrong thing there, unless you want the
stds::pair<Key*,Value> referenced by the iterator to be copied into a
new Python object.  I don't think you've wrapped
std::pair<Key*,Value> have you?

http://www.boost.org/libs/python/doc/v2/ResultConverter.html
describes the requirements for apply<T>::type.  Its convertible()
function should return true and its function-call operator should
produce a PyObject* (owned reference).  Something like

        PyObject* operator()(std::pair<KeyType*,Value> const& x) const
        {
            return python::incref(
                python::object(ptr(x.first)).ptr()
            );
        }

ought to work.

HTH,
-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com





More information about the Cplusplus-sig mailing list