
Richard Smith <richard@ex-parrot.com> 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