Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2006-07-12 15:41:28


Richard Smith <richard_at_[hidden]> writes:

> The Standard's table of InputIterator requirements
> (table 72 in section 24.1) says that, amongst other things,
> an InputIterator must support the following two expressions:
>
> *a Convertible to T, the iterator's value_type
>
> a->m Equivalent to (*a).m
>
> The same language is present in the "New Iterator Concepts",
> N1550, documentation in the definition of ReadableIterator.
>
> In particular, InputIterators are allowed to, and often do,
> have operator* returning by value:
>
> template <typename T> class my_iterator {
> public:
> typedef T value_type;
> T operator*() const;
> // ...
> };

Yes.

> Because it is legal to call non-const member functions on temporary
> objects,

Only if they're non-const.

> it is legal to call non-const member
> functions on the value returned from operator*:
>
> struct foo {
> void non_const();
> };
>
> my_iterator<foo> i;
> (*i).non_const();

No. The value returned from operator* might be a const proxy with a
(const) conversion operator to value_type.

> My reading of Table 72 documentation suggests that this
> means that for my_iterator<foo> to be a Readable Iterator,

Table 72 doesn't describe Readable Iterator.

> it must also be legal to write:
>
> i->non_const();

All Table 72 says about operator-> is

    a->m precondition: (*a).m is well-defined
    Equivalent to (*a).m

> If so, this means that operator-> should return T* instead
> of T const* (possibly via a proxy class).

If operator* returns value_type, I think I agree that operator->
should return T* or an equivalent proxy pointer.

> In the current implementation of boost::iterator_facade, operator->
> returns a proxy that acts as a T const*:
>
> template <class T>
> struct operator_arrow_proxy
> {
> operator_arrow_proxy(T const* px) : m_value(*px) {}
> const T* operator->() const { return &m_value; }
> operator const T*() const { return &m_value; }
> T m_value;
> };
>
> Is there a reason not to change this to have operator->
> returning a T*? That would seem closer to the defintion of
> an InputIterator.

I agree with you in principle. I think there's something missing in
our concept checks that this wasn't picked up.

> (I supposed that if operator* returns by const value, it
> would be necessary to resurrect the constness in the proxy,
> but assuming the iterator's reference typedef is also a
> const-qualified value, this should be easy enough.)
>
> I had a look at the current concept-based iterator proposal,
> N2039, to see whether that shed any light on this and it
> also seems to require this behaviour from an InputIterator.
> It formal concept only requires operator->'s return to be
> convertible to T const* (which T*, or a proxy to T*, is):
>
> concept InputIterator<typename X> {
> where /*...*/ Convertible<pointer, value_type const*>;
> pointer operator->(X);
> //
> }
>
> And in it's definition of operator->, it requires (*a).m to
> be well-formed and then defines a->m to be equivalent to it.
>
> Have I misunderstood some aspect of this, or does the
> Standard really all require that a generic input iterator
> adaptor, such as boost::iterator_adaptor (and by
> impliciation boost::iterator_facade) should support this?

I think you're right. Please enter a bug report at SourceForge so
this doesn't get lost.

Thanks for the report,
Dave

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

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