Topic: Return type of operator->()
Author: gjditchfield@watmsg.uwaterloo.ca (Glen Ditchfield)
Date: Mon, 1 Apr 1991 16:23:52 GMT Raw View
There are restrictions on the allowed return type of operator->(). Where
should they be enforced? I think they should be enforced at the call site,
not the declaration, at least when templates are involved.
Chapter and verse: the ARM, section 13.4.6, "Class Member Access" says
"it follows that operator->() must return either a pointer to a class or an
object of or a reference to a class for which operator->() is defined."
So the following is illegal:
struct s {
int operator->(); // cfront 2.1 complains about this line.
};
void f() {
s an_s;
s->m; // g++ 1.37.1 complains about this line.
}
I think the g++ behaviour is "more standard", because s. 13.4.6 is about
"->" expressions, not declarations. In other words, the sentence means "it
follows that the result of a -> expression must be either..." (There is
also the statement near the top of p. 331: "Note that--except for operator
new() and operator delete()--there are no restrictions on the return types
of overloaded operators." But that statement is in an annotation, so it
doesn't really count.)
The g++ "illegal when called" approach makes it easier to write template
classes that define operator->(). Consider a template for a Set class that
contains copies of values as opposed to pointers to objects. Set comes
with a companion Generator class. Generators act like constant objects of
a set's element type. They take on each of the values in a set in turn,
and are used as loop indices.
template<class Elt> class Set;
template<class Elt> class Generator { ...
public:
operator Elt(); // Copy the current value.
const Elt operator->(); // Member access through current value.
void in(Set<Elt>&); // Begin generating values.
friend int more(Generator); // Are there more values?
friend void next(Generator&); // Go get the next value.
};
Set<int> si;
Generator<int> gi;
int sum_sq = 0;
for (gi.in(si); more(gi); next(gi)) // for every element in si ...
sum_sq += gi*gi; // Conversion via operator Elt().
Generator has an operator->() in case Elt is a pointer to a class.
class Employee { ... };
Set<Employee*> se;
Generator<Employee*> ge;
for (ge.in(se); more(ge); next(ge)) // for every element in se ...
cout << ge->name << ge->department;
However, a compile-time error message should be generated if operator->()
is applied to a Generator<int>. If the rules about result types are
enforced when operator->() is used, then an error will be reported if
_and_only_if_ "->" is applied to a Generator<int>. If the rules are
enforced when operator->() is declared, then either the template or the
instantiation Generator<int> will produce an error, and this Generator
approach must be abandoned.
Glen Ditchfield gjditchfield@violet.uwaterloo.ca Office: DC 2517
Dept. of Computer Science, U of Waterloo, Waterloo, Ontario, Canada, N2L 3G1
These opinions have not been tested on animals.