|
Boost : |
From: Richard Smith (richard_at_[hidden])
Date: 2006-07-12 09:27:47
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;
// ...
};
Because it is legal to call non-const member functions on
temporary objects, 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();
My reading of Table 72 documentation suggests that this
means that for my_iterator<foo> to be a Readable Iterator,
it must also be legal to write:
i->non_const();
If so, this means that operator-> should return T* instead
of T const* (possibly via a proxy class). 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 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?
-- Richard Smith
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk