[C++-sig] map key
David Abrahams
dave at boost-consulting.com
Fri Jan 17 23:29:28 CET 2003
"Mike Rovner" <mike at bindkey.com> writes:
> I'm trying to wrap a std::map<const Key*, Value> with
>
> template<class T>
> struct map_item
>
> {
>
> typedef typename T::key_type Key;
<snip>
Mike, lots of mailers don't respond well to indentation with tabs.
Cleaning up your code, I get:
template<class T>
struct map_item
{
typedef typename T::key_type Key;
typedef typename T::mapped_type Value;
static Value const& get(T& x, const Key n)
{
if( x.find(n) != x.end() ) return x[n];
PyErr_SetString(PyExc_KeyError,"Map key not found");
throw_error_already_set();
}
static void set(T& x, const Key n, const Value& val) { x[n]=val; }
static void del(T& x, const Key n) { x.erase(n); }
static bool in(T const& x, const Key n) { return x.find(n) != x.end(); }
static list keys(T const& x)
{
list t;
for(T::const_iterator it=x.begin(); it!=x.end(); ++it)
t.append( object(it->first) );
You don't need this---^^^^^^^---------^
return t;
}
static list values(T const& x)
{
list t;
for(T::const_iterator it=x.begin(); it!=x.end(); ++it)
t.append( object(it->second) );
You don't need this---^^^^^^^----------^
return t;
}
static list items(T const& x)
{
list t;
for(T::const_iterator it=x.begin(); it!=x.end(); ++it)
t.append( make_tuple(object(it->first), object(it->second)) );
You don't need this--------------^^^^^^^---------^--^^^^^^^----------^
return t;
}
};
typedef std::map<const Key*, Value> Map;
class_<Key, boost::noncopyable>("Key", no_init) /*...*/;
class_<Value>("Value") /*...*/;
class_<Map>("Map")
.def("keys", &map_item<Map>::keys)
;
--
> My problem is to return keys:
>
>>>> m=Map(...)
>>>> m.keys()
>
> TypeError: No to_python (by-value) converter found for C++ type:
> class Key
>
> Other functions returning const Key* are just fine with
> return_internal_reference.
There is no function returning const Key* being invoked, but I see
what you mean. The problem occurs where you try to convert a ``const
Key*'' to a Python object.
> Can I specify return_internal_reference when constructing keys list?
Hum, that's an interesting question. I guess you'd like each of the
items in the keys list to keep the map object alive so that they will
remain valid. You could use t.append(ptr(it->second)), which would
build an object around the pointer and stick it in the list, but that
would not have the desired lifetime-management properties.
One approach would be to wrap a function which could convert
the pointer with the lifetime management you want:
Key const* managed(object map, Key const* x) { return x; }
object py_managed = make_function(managed, return_internal_reference<>());
Then you need to get ahold of the map's Python object in your keys
function:
static list keys(python::back_reference<T const&> xx)
{
T const& x = xx.get();
list t;
for(T::const_iterator it=x.begin(); it!=x.end(); ++it)
t.append( py_managed(xx.source(), it->first) );
return t;
}
> How? Will it solve the problem?
I think that would solve it.
Mike, I think this would make a really good tutorial case study for
the Boost.Python documentation. Is there any way I could persuade you
to write it up so that others can benefit?
--
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