Document Number: WG21/N0719
Date: 8 July 1995
Project: Programming Language C++
Reply to: Sean A. Corfield
The checking of the return type of operator->() declared within a template
is deferred to the point of use (to enable pointer-like template classes
to be written for arbitrary types). The STL introduced iterators into the
standard library and these have pointer-like behaviour with the notable
omission of operator->(). Furthermore, the restrictions on the return type
would not seem to need to apply to explicit invocations of operator-> since
such invocations do not require a member name.
This paper proposes that the iterators defined in the standard library
provide operator->() where it is appropriate to do so. This paper also
proposes that the return type restriction be revised in general to be
applied only at the point of use for the implicit invocation in x->m.
The paper is in two independent parts.
Part 1 - iterators and operator->()
This relates to clause 24 issue 10 in N0702 = 95-0102.
What does operator->() mean for input and output iterators? For practical
purposes, the uses would be as follows:
x = it->m;
it->m = y;
In current terms these would be equivalent to:
x = (*it).m;
(*it).m = y;
It seems reasonable that the former be valid exactly when the latter are
and have exactly the same semantics. For output iterators, it is not clear
how a member only can be assigned, so this proposal leaves that issue open
(as in the issues list N0702 = 95-0102).
Add operator->() to the requirements for all iterators except output
Programmers will expect operator-> to be defined for pointer-like objects
which iterators claim to be. For output iterators, we can argue that it is
the entire referenced object which acts as the sink and allowing operator->
would lead to partially uninitialised objects -- this would seem to be
undesirable. Under the current semantics, '(*out_it).m = x;' does not
make sense anyway.
In 24.1 [lib.iterator.requirements], after:
All iterators i support the expression *i,
resulting in a value of some class, enumeration, or built-in type T,
called the value type of the iterator.
All iterators i for which the expression (*i).m is well-formed support
the expression i->m with the same semantics as (*i).m.
In the requirements table for input iterators, add:
a->m T return (*i).m pre: (*i).m is well-formed and has type T
(Should a different type to 'T' be used here?)
[Note: output iterators do not require operator-> to be defined]
In the requirements table for forward iterators, add:
a->m T& return (*i).m pre: (*i).m is well-formed and has type T
(because the expression (*i).m cannot have reference type).
In 184.108.40.206 [lib.reverse.bidir.iter], in the declaration of the template
class reverse_bidirectional_iterator, add the following member declaration:
After 220.127.116.11.3 [lib.reverse.bidir.iter.op.star] add a new sub-clause
[lib.reverse.bidir.iter.op.points] with the following text:
BidirectionalIterator tmp = current;
Part 2 - relaxing the restrictions on the return type of operator->()
Note in the above WP changes that defining operator->() for the reverse
bidirectional iterator uses the explicit invocation of the function called
operator-> on the adapted iterator. There is no reason why this would not
be appropriate in other situations too. There is also no reason why the
return type of operator->() should be constrained to be a pointer to class
type in these situations.
Relax the restriction on the return type of operator->() so that checking
is performed only for the implicit use in expressions such as x->m for both
the template and non-template case.
Delete 14.3.3 [temp.opref].
In 13.5.6 [over.ref], paragraph 1, delete:
operator-> shall return either a pointer to a
class or an object of or a reference to a class for which operator->
is defined, except in some cases when it is a member of a template
(see _temp.opref_). T::operator-> shall not return an object of or
reference to its own class type T.
Since 5.2.4 [expr.ref] already has restrictions on the lhs of ->, no
further changes are required.