[C++-sig] Re: Adding __len__ to range objects

Raoul Gough RaoulGough at yahoo.co.uk
Thu Sep 4 01:02:24 CEST 2003


"Joel de Guzman" <djowel at gmx.co.uk> writes:

> Raoul Gough <RaoulGough at yahoo.co.uk> wrote:
>> "Joel de Guzman" <djowel at gmx.co.uk> writes:
>
>> Well, I've had a go anyway. I've produced a container_proxy template
>> that wraps a random-access container and provides access via element
>> proxies. The element proxies provide an implicit conversion to the raw
>> value type, and also a constructor from the raw value type, which
>> means that it works with an unchanged[*1] vector_indexing_suite as
>> follows:
>> 
>> vector_indexing_suite<container_proxy<VectorType>, true>
>
> This is great! Did the current tests pass with the new code?

[taking a look at libs/python/test] Hey! You've already written some
tests :-) I didn't know about these, but I guess I should have looked
there automatically.

It turns out that the find() functionality needs some additional
comparison operators in the element_proxy. I've added these, and the
vector indexing tests now run without failure. It still requires some
minor tweaks outside of the suite to make it work (i.e.
register_ptr_to_python and implicitly_convertible).

Getting register_ptr_to_python to work seemed a little more difficult
than I would have expected. In particular, the need to specialize
boost::get_pointer probably means making the element_proxy a
non-nested class, since it has to be a deducible type:

template<typename T, typename U, typename V>
typename container_proxy<T,U,V>::element_proxy::value_type
... get_pointer (container_proxy<T,U,V>::element_proxy);

Which I believe doesn't work. I've just provided a non-template
overload for the test cases. I also had to add an "element" typedef to
keep something else happy, and also (at some earlier stage)
iterator_category and difference_type. This all reinforces my thoughts
from a few weeks back, about the need for some kind of centralized
handle_traits or proxy_traits.

[snip]
>> Sample output:
>> 
>> copy is 3, v[1] is 3
>> copy is 5, v[1] is 5    # Wrong - copy should remain unchanged
>> 
>> The container_proxy wrapper fixes that problem (whatever it is,
>> probably minor) but doesn't fix the following additional problem, that
>> both versions exhibit:
>
> Indeed. It's nice to hear that container_proxy fixed this.
>
>>     slice = v[1:2]
>>     print "slice[0] is %s, v[1] is %s" % (slice[0], v[1])
>> 
>>     v[1].increment()
>>     print "slice[0] is %s, v[1] is %s" % (slice[0], v[1])
>> 
>> Sample output:
>> 
>> slice[0] is 5, v[1] is 5
>> slice[0] is 5, v[1] is 6  # Should be slice[0] is 6, v[1] is 6
>> 
>> This may be a fundamental problem with how slices are returned.
>> Compiler is gcc 3.3.1 (mingw special 20030804-1).
>
> Right. slices are currently returned by value. I guess this is another
> area to be explored. I think I know how to deal with it. Let's do
> it when we refactor the slicing stuff. I think this is a good start. There
> are lots of things to do and I certainly am glad that you can help. I've
> already been bitten by the wholesale approach of the current indexing
> suites (more on that later) that I really need to break it up sometime
> soon!

I've also been thinking about the slice return value problem, and I
believe the best answer is to return a real Python list containing
element proxies. My reasoning is that we can't return a container of
identical type to the original, since it has value semantics and we
need reference semantics to be at all Python-like. Unfortunately, this
means that the following won't work:

# Given wrapped C++ function foo (std::vector<bar> const &)

foo (v)      # OK - called on std::vector<bar>
foo (v[1:4]) # !OK - called on Python list

Then again, it also wouldn't work if v[1:4] was a wrapped
vector<element_proxy>, so why not just use a real Python list and save
some template instantiation work. Actually, I'm not sure whether
creating a working vector<element_proxy> wrapper might not mean more
programming work for us as well, in which case I'm definitely against
it :-)

My latest code is available from the boost-sandbox CVS in the
boost-sandbox/boost/python/suite/indexing directory. Note: could it be
that the anonymous server is out of date with the SSH one? I could
only retrieve the stuff I added via the
:ext:raoulgough at cvs.boost-sandbox...  path.

-- 
Raoul Gough.
(setq dabbrev-case-fold-search nil)





More information about the Cplusplus-sig mailing list