gjditchfield@watmsg.uwaterloo.ca (Glen Ditchfield) (04/02/91)
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.