Added package with the documentation and the examples
[lwc.git] / doc / 4.2.operator-overloading
blob87269dc1f734377b8aae05a2ce9f3c5091a25200
2 Operator Overloading
3 ====================
5 operator overloading is fun because it makes programs
6 more interesting as it can give new meanings to strange
7 symbols (most of which are unused for structures), and
8 make your code more cryptic and impressive.  
11 0. Fun example
12 ~~~~~~~~~~~~~~
14 In this example we will overload '~' for pointers to
15 free the memory and '!!' for strings to print a message
16 on stderr.  These two operators are by default invalid
17 on pointer operands ('!!' is a new operator of lwc which
18 toggles boolean values prefix or postfix. after the introduction
19 of the postfix() '!!' is redundant and can be
20 used as a free operator for overloading).
22         void operator ~ (void *p)
23         {
24                 free (p);
25         }
27         void operator !! (char *c)
28         {
29                 fprintf (stderr, "%s\n", c);
30         }
32         int main ()
33         {
34                 !! "Hello World!";
36                 char *x = malloc (100);
37                 strcpy (x, "Bye");
38                 !!x;
39                 ~x
40                 ~(int)x;        // force complement
41         }
44 We can extend this example, overloading the binary comma operator
45 to make an experimental and fun output facility subsystem:
47         extern "stdio.h" {
48         #include <stdio.h>
49         }
51         FILE* operator, (FILE *f, int i)
52         {
53                 fprintf (f, "%i", i);
54                 return f;
55         }
57         FILE* operator, (FILE *f, void *p)
58         {
59                 fprintf (f, "%p", p);
60                 return f;
61         }
63         FILE *operator, (FILE *f, char *s)
64         {
65                 fprintf (f, "%s", s);
66                 return f;
67         }
69         int main ()
70         {
71                 int i = 3;
72                 char *p = "text";
75                 stdout, "The values are: ", i, " and ", (void*)p, " [", p, "]\n";
76         }
79 ________________________
80 1. Operators for objects
81 ~~~~~~~~~~~~~~~~~~~~~~~~
83 operators for objects can be defined as member functions or
84 global functions where the first argument is a structure.
85 The difference is that member functions are inherited and
86 can be virtual.  Apart from that the two forms are the same.
88 From the 46 operators of C, 43 do not make sense for structures.
89 From these, 26 do not make sense even if the operand is a
90 pointer to a structure.  Unlike c++, in lwc operator overloading
91 works for structures and *pointers to structures*.
94 1a. Safe operators
95 ~~~~~~~~~~~~~~~~~~
97 The operators that make sense only with arithmetic operands are:
99         unary: + - ~ !!
100         binary: * / % | ^ & , *= /= %= ^= |= &= << >> <<= >>=
101         postfix: !! ()
103 Overloading those is safe and the overloaded action will be used
104 even if the operands are *pointers to structures*.  For example:
106         class A {
107                 int i;
108                 void operator + ()              { i = 0; }
109                 void operator * (int j);        { i += j; }
110                 void operator () (int x, int y) { i = x - y; }
111         };
113         int main ()
114         {
115                 A a, *ap = &a;
117                 // on objects
118                 +a;
119                 a * 1;
120                 a (1, 2);
122                 // on pointers
123                 +ap;
124                 ap * 1;
125                 ap (3, 4);
126         }
128 In all the cases, the overload functions will be called.
131 1b. Unsafe operators
132 ~~~~~~~~~~~~~~~~~~~~
134 The operators below make sense if the operand is a pointer
135 to an object and so lwc will not use operator overloading in
136 this case. To insist of overloading, the operator function can
137 be forced by using "->operator".
139         unary: * ++ -- !
140         binary: + - > < >= <= == != && || += -=
141         postfix: ++ --
143 An example:
145         class A {
146                 float f;
147                 void operator * ()      { f = 0; }
148                 bool operator == (A a)  { return fabs (a.f - f) < 0.001; }
149                 float operator + (float x)      { return f + x; }
150                 int operator + (int x)          { return f + x; }
151                 A operator - (A a)              { A r; r.f = f - a.f; return r; }
152                 A operator + (A a)              { A r; r.f = f + a.f; return r; }
153         };
155         int main ()
156         {
157                 A a, *ap = &a, b, *bp = &b;
159                 // structures
160                 *a;             // overload
161                 a == b;         // overload
162                 a + 1.0;        // overload
163                 a + b;          // overload
164                 a - b;          // overload
166                 // pointers
167                 *ap;            // default action: pointer indirection
168                 ap == bp;       // default action: comparison
169                 ap + 1;         // default action: ptr arithmetic
170                 ap - bp;        // default action: ptr arithmetic
172                 // pointers + forced operator
173                 ->*ap;          // overload
174                 ap ->== bp;     // overload
175                 ap ->+ 1;       // overload
176                 ap ->- bp;      // overload
178                 // pointers + invalid expressions
179                 ap + 1.0;       // overload: makes no sense ptr + float!
180                 ap == b;        // overload: makes no sense ptr == obj!
181                 ap + bp;        // overload: makes no sense ptr + ptr!
183                 ap ->+ 1.0;     // overload for both reasons
184         }
186 As it can be seen, lwc will not use the overloaded function if:
187  the base operand is a pointer && the action is not forced by
188  enclosing the operator in parentheses && the operation is valid.
190 Whether operations are valid is checked for:
191         + +=    : valid if other operand  int
192         - -=    : valid if other operand  int or ptr
193         == !=
194         <= >=
195         > <     : valid if other operand  not float and not structure
196         && ||   : always valid unless other operand a structure
199 1.c Postfix ++ -- !!            (new in lwc 1.1)
200 ~~~~~~~~~~~~~~~~~~~~
202 The keyword 'postfix' must be used after 'operator'. Example:
204         class A {
205                 int i;
206                 int operator ++ ()              { return ++i; }
207                 int operator postfix ++ ()      { return i++; }
208         };
210         int f ()
211         {
212                 A a;
213                 a++;
214                 ++a;
215         }
217 1.d Array operator
218 ~~~~~~~~~~~~~~~~~~
220 This is also an unsafe operator as the 1b section.  What is special
221 is how to force operator overloading on the operator.
223         class A {
224                 float f [100];
225                 float &operator [] (int i)      { return f [i]; }
226         };
228         int main ()
229         {
230                 A a, *ap = &a;
232                 a [12] = 3.14;          // overload
233                 ap [12];                // default action: ptr arithmetic, result 'struct A'
234                 ap ->[12] = 3.14;       // overload
235                 ap [12][12] = 1.41;     // overload on 12th element of ap array
236         }
239 1e. Very Unsafe operator
240 ~~~~~~~~~~~~~~~~~~~~~~~~
242 This is the '=' operator. Normally, it makes sense in all cases.
243 If overloaded, it will always use the overloaded version for structures
244 and the default action for pointers. So this works exactly like the
245 unsafe operators.  Also note that this is not a copy constructor:
246 it is not invoked in declaration initializations.
248 The second operator is '->' which works ONLY for objects. See "5.0.new-in-.."
251 1f. Non overloadable
252 ~~~~~~~~~~~~~~~~~~~~
253 Non-overloadable operators at the moment are:
255         unary:  & (cast) sizeof delete new localloc
256         postfix: .
258 There are reasons for not overloading each of these.
259 Send proposals to the mailing list.
262 * 1g. New in lwc-1.0 *
263 ~~~~~~~~~~~~~~~~~~~~~~
264 As an exception to whether overloading on unsafe operators is permitted,
265 if the first operand is 'this' overloading takes place.  For example:
267         class A {
268                 int &operator [] (int i) {
269                         return g [i];
270                 }
271                 int &operator += (int i) {
272                         return g [0] += 13;
273                 }
274                 int f () {
275                         this [12] = this [13];  // operator overload!
276                         this += 24;             // overload
277                         this += this [12];      // overload
278                         (A*) this += 12;        // default action
279                         ((A*)this) [1] = 3;     // default action
280                 }
281         };
283 This happens for all the dangerous operators except:
284         unary * and binary == and !=
286 _________________________
287 2. An interesting example
288 ~~~~~~~~~~~~~~~~~~~~~~~~~
290 An interesting example where we implement our own complex
291 number arithmetic.
294         extern "stdio.h" {
295         #include <stdio.h>
296         };
298         class A {
299                 float re, im;
300                 ctor (float r, float i) {
301                         re = r, im = i;
302                 }
303                 A operator + (A a) {
304                         A r;
305                         r.re = re + a.re;
306                         r.im = im + a.im;
307                         return r;
308                 }
309                 A operator - (A a) {
310                         A r;
311                         r.re = re - a.re;
312                         r.im = im - a.im;
313                         return r;
314                 }
315                 A& operator = (A a) {
316                         re = a.re;
317                         im = a.im;
318                         return this;
319                 }
320                 A& operator += (A a) {
321                         re += a.re;
322                         im += a.im;
323                         return this;
324                 }
325                 A& operator *= (float f) {
326                         re *= f;
327                         im *= f;
328                         return this;
329                 }
330                 void operator !! () {
331                         printf ("[%.3f %.3f]\n", re, im);
332                 }
333         };
335         int main ()
336         {
337                 A c1 (1, 2), c2 (3, -1);
338                 A c, cc (1, 1);
339                 A c4 (-1, -1), c5;
341                 cc += c = c1 + c2;
342                 c5 = c4 + (cc += c = c1 + c2) + c4;
344                 c5 *= 3;
345                 c5 *= 1.0/3.0;
346                 !!c1, !!c2, !!c, !!cc;
347                 !!c4, !!c5;
348         }
350 The interesting thing demonstated in this program is when to return a
351 reference and when to return an object.  A reference should be returned
352 when the object is modified and the result is an-lvalue.  On the other
353 hand when the operation is a temporary value, a temporary object should
354 be returned.
356 A problem with lwc at the moment is that it will call the destructor of
357 the object of, say, function '-' while it will not call the constructor
358 of the temporary object where the return value will be placed.  In simple
359 words, we can't use this technique yet on object that allocate/free memory
360 at their construction/destruction, or do other critical things there.
363 ______________________________________
364 3. lwc && structure by reference calls
365 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
367 In lwc, structures are always passed by reference.  Moreover, as explained
368 in the tutorial, both a structure and a pointer to a structure can be
369 passed to such reference arguments.  The lwc preprocessor will make the
370 necessary conversions.  As a result, it is possible that the one operand
371 will be an object and the other a pointer to an object.  It will work.
373         class A {
374                 void operator == (A);
375         };
377         int test ()
378         {
379                 A a, *ap;
381                 ap == a;
382                 a == ap;
383         }