TITLE: Type promotions and global operators ......................................................................... PROBLEM: ??? friend Complex operator+ ( const Complex &, float); friend Complex operator+ ( const Complex &, int); friend Complex operator+ ( const Complex &, double); ......................................................................... RESPONSE: p j l @cs.uiuc.edu (Paul Lucas) friend Complex operator+( Complex const&, Complex const& ); Complex( double,double=0.0 ); (Why write unnecessary code?) ......................................................................... RESPONSE: daniel@cse.ucsc.edu (Daniel R. Edelson) Because the resulting code is more efficient. ......................................................................... RESPONSE: pjl@cs.uiuc.edu (Paul Lucas) Supplying all of the different addition operators allows the operations to be performed directly, without the intervening type conversions. This saves instructions and memory references. int, unsigned int long, unsigned long float, double Complex That's 81 possible combinations times 4 for */+- which is 324 functions. Be my guest at coding them all (correctly). Funny...C++ has features like type-conversion just so people *won't* use them?? The minor delta in performance is negligable unless you absolutely have to squeeze out every last bit of speed; I would guess that most people don't need to go to such lengths. Also, in the case of Complex, the c'tor is trivial anyway. ......................................................................... RESPONSE: daniel@cse.ucsc.edu (Daniel R. Edelson), 13 Jan 93 In this case, the conversions among the built-in types (integral and floating point) are necessary to obtain the result. That is, even if you furnish: friend complex operator + (complex, char); inside the implementation of this operator you must convert the char operand to a double to perform the addition. Thus, it is appropriate to provide a single addition operator of complex and double whose second actual argument is subject to the standard propotions and integral and floating point conversions. There is absolutely no difference in efficiency in providing only this operator or the whole suite of unsigned char through double. However, converting the integral or floating point operand to a complex entails unnecessary operations. The converted value's imaginary part is first initialized and then assigned to the result of the addition. Both these operations are unnecessary. These benefit of avoiding this becomes even greater when you inline the addition operation. Of course, this doesn't preclude supplying the converting constructor in addition. The overloading mechanism will select the assignment operator that doesn't require a user-defined type conversion. Consider the following: // class complex struct complex { double re, im; complex() : re(0), im(0) { } complex(double d) : re(d), im(0) { } complex(double r, double i) : re(r), im(i) { } }; // add both fields of two complex numbers inline complex operator + (complex z1, complex z2) { return complex(z1.re + z2.re, z1.im + z2.im); } // add a double directly to the real part of a complex inline complex operator + (complex z, double d) { return complex(z.re + d, z.im); } Now, we write some sample code that calls the addition operators the two ways: complex = complex + complex(double) complex = complex + double // This routine calls inline operator +(complex,double) complex foo(complex z, double d) { return z + d; } // This routine calls inline operator +(complex,complex) complex bar(complex z, double d) { return z + complex(d); } int main(void) { return 0; } On a SPARC with Cfront 3.0.1 and gcc 2.3.3 compiled with CC -O -S c.c the functions foo() and bar() compile to the following: foo() { <24 asm statements deleted> } bar() { <36 asm statements deleted> } I think 24 instructions versus 36 is a sufficiently important benefit to make the extra effort worthwhile. I find one of the hardest parts of understanding C++ code is identifying the hidden operations. I've had students who expressed the opinion that C++ is a radical divergence from C because of the number of such hidden operations in superficially innocuous code. I advise them to understand well the type-conversion behavior of their code, and to limit the number of user-defined type conversions they supply and utilize. I think this is good advice.