Boost logo

Boost :

Subject: Re: [boost] [iterator] [iterator_facade] operator-> question
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2011-06-30 19:26:46


On Thu, Jun 30, 2011 at 3:50 PM, Dave Abrahams <dave_at_[hidden]> wrote:

> At Wed, 29 Jun 2011 13:09:04 -0700,
> Jeffrey Lee Hellrung, Jr. wrote:
> >
> > Now, iterator_facade< /*...*/ >::operator->'s return type is
> > operator_arrow_result< /*...*/ >::type, which, for proxy references,
> > according to the logic above in operator_arrow_result, is
> > operator_arrow_proxy<T>, where T, in this case, is pair< Index, Value >.
> > The error occurs when operator_arrow_proxy<T> is constructed from &x
> within
> > operator_arrow_result< /*...*/ >::make, as it tries to convert a pair<
> > Index, Value& >* to a pair< Index, Value >*, which is a no-go.
> >
> > It seems to me that a more correct implementation of
> operator_arrow_result
> > would use operator_arrow_proxy< Reference > rather than
> > operator_arrow_proxy< ValueType >.
>
> That won't get us what we need: an actual T lvalue as noted in the comment.
>

Well to be perfectly accurate, the comment says nothing about a *T* lvalue,
it only states: "If *i is not a reference type, we must still produce a
lvalue to which a pointer can be formed." I'm assuming here that you meant
T to be the iterator's value_type. As long as operator_arrow_proxy is
wrapping an *object* (a proxy reference qualifies), you'll ultimately get a
pointer to *some* lvalue through the chain of operator->'s (...right? At
least I thought that's how operator-> worked...). And if you want
(*i).member to be equivalent to i->member, then it seems to me that the
operator_arrow_proxy has got to be wrapping the proxy reference, not a
value_type object. As far as I'm concerned, the last row of the table at

http://www.boost.org/libs/iterator/doc/ReadableIterator.html

*almost* requires operator_arrow_proxy to store the proxy reference, not the
value_type object...I say "almost" since the Concept is premised on U being
a member of T, but it seems the *intent* nonetheless is for i->member to be
equivalent to (*i).member.

Even if you want operator_arrow_proxy to wrap a value_type object and return
a value_type* for its operator->, the code is still trying to implicitly
cast a reference* (or whatever the result of &(*i) is) to a value_type const
*, and I just don't see how one expects that to compile generally. I.e., I
don't recall any iterator requirements on the result of &(*i) being
convertible to value_type const *...

> I would further rename and change operator_arrow_proxy's member
> > variable to be stored as const T m_ref, rather than mutable T
> > m_value.
>
> Is that related to this problem?
>

No. I'm only claiming that all operations on the proxy reference should
logically not mutate the proxy reference itself, only its referent, hence it
should be correct to store it by constant value and return a
pointer-to-const in operator->.

> > What are others' opinions on this? Am I doing something wrong?
>
> I doubt you're doing anything wrong. I'm fully prepared to believe
> the library should be doing something smarter. What that smarter
> thing is, I am not sure of, but you might find the answer in one of
> the many outstanding tickets.
>

I will browse, and maybe add a ticket. I guess I should also check the
tests to see if this case is covered.

- Jeff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk