$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: David Abrahams (dave_at_[hidden])
Date: 2004-12-06 14:25:11
Tobias Schwinger wrote:
 > David Abrahams wrote:
 >
 >> But why not just change the interface in your dereference function and
 >> hand back a real reference at that point?  If you are not storing a
 >> copy of the value_type within the proxy, I don't see what the proxy
 >> can be buying you.
 >>
 >
 > I'll put a short problem-domain-specific excursion at the end of this
 > post which explains what exactly the proxy is buying me.
Thanks.
 >> So now we come to this one.  This one is entirely in the hands of the
 >> library to prevent, since the user doesn't usually determine the
 >> return type of operator->.  It seems like a bad idea to allow it
 >> silently.
 >> The library is supplying an operator-> that stores an object of the
 >> value_type.  There are very few situations where modifications to that
 >> object can go anywhere useful, so it makes sense to prevent them.
 >
 >
 > Doesn't the fact that reference and value_type are the same and both 
are
 > mutable class types indicate that this should work as well ?
Ah.  Well now, that is a special case.  Maybe we should allow it
whenever reference is the same as or derived from value_type.
Incidentally, I don't call that case a proxy -- as far as I'm
concerned that's just an ordinary non-lvalue iterator.  I suppose
if your value_type is really a refcounted pimpl it is somewhat
proxy-like, though.  Incidentally #2, the library is focused
mainly on building generic iterators so we usually didn't
consider the fact that class value_type objects returned by value
from an iterator's operator* might be assigned into.
 > After all, it should be just another notation for
 >
 >   (*i).mutator(value)
 >
 > from a user's perspective.
 >
 >
 >> The library is able to make sensible default choices without fear
 >> because the user can always reimplement any operator within his
 >> derived iterator.
 >>
 >
 > My workaround to allow it feels somewhat ugly, because I have
 > to redundantly do the same thing iterator_facade does already
 > (use yet another proxy to aggregate my temporary reference
 > object and make its operator-> return a pointer to it - just
 > like operator_arrow_proxy (given that reference and value_type
 > are the same), except that there is a non-const operator->,
 > too).
Understandable.
 > !!! However, it works for me. I don't want to try to make you change
 > things for what could be a special case !!!
 >
 > I'm not too sure calling mutators on a proxy class really is that
 > special, though.
It's not so special, but building a proxy reference that fully
emulates the interface of the referenced value type is quite
unusual.  It's takes a lot of work, is very fragile and can't be
done generically.
 >>> ...and I can't imagine there is a user who would seriously complain 
that
 >>>
 >>>   pointer ptr ( i.operator->().operator->() );
 >>>
 >>> gives an invalid pointer ;-).
 >>>
 >>>
 >>>
 >>> Am I missing something ?
 >>
 >>
 >>
 >> There was a guy who complained just last week on this very mailing
 >> list that putting an iterator_adaptor over a T const* suddenly
 >> produced writability in the iterator through operator-> !!
 >> http://listarchives.boost.org/MailArchives/boost-users/msg08656.php
 >
 > Yeah, I (partially) read it to ensure I am not asking redundant
 > questions before starting this thread. I still believe adapting
 > pointers is a different story.
It's not such a different story.  If I take a non-writable
version your iterator, operating correctly, and wrap
iterator_adaptor around it, it would be very strange if
operator-> allowed you to mutate members.
 > Excursion: what's the proxy buying me ?
 >
 > I use a generic, resizable container (similar to std::vector
 > but with memory layout guarantees) to feed vector data to my
 > graphics board through some rendering API.  The proxy allows me
 > to see a vector object instead of a reference to an array of
 > floating type.
 >
 > Operating on plain arrays in order to perform vector
 > arithmetics is quite unhandy.  Using a converting constructor
 > from a reference to array type is a radical and error prone
 > approach and would restrict me to use only one class for vector
 > arithmetics (there is no way to tell if float[3] should be a
 > homogenous 2D-vector or a non-homogenous 3D-vector, for
 > example).
 >
 > That's why I use a vector-reference proxy class that allows me
 > to work on vectors whose data lives somewhere else.
I understand, thanks.
-- Dave Abrahams Boost Consulting http://www.boost-consulting.com