spalding@uiucdcsp.cs.uiuc.edu (01/05/88)
I think the best way to control type conversion of arguments is to make the arguments class objects instead of simple types. Then you can control how the arguments are converted. Each argument can be controlled individually, so you avoid the problem of excessive numbers of overloaded functions. In the color example, define a class color with constructors for each type you want to allow: #include <stream.h> class color { public: float intensity; color(float i) {intensity = i;} color(int i) {intensity = i / 255.0;} }; void show(color red, color green, color blue) { cout << "red: " << red.intensity << ", green: " << green.intensity << ", blue: " << blue.intensity << "\n"; } main() { show(0.5, 0.25, 255); show(127, 1.0, 0); } This program produces the following output: red: 0.5, green: 0.25, blue: 1 red: 0.498039, green: 1, blue: 0 If you don't want to allow the integer arguments, just remove the second constructor and the compiler produces the following error messages: CC colors.c: "colors.c", line 18: error: cannot make a color from a int "colors.c", line 19: error: cannot make a color from a int 2 errors The second problem of forcing programmers to use macros you've set up for particular parameters can also be solved with classes. In this case, the constructor has a second (unused) argument so that C++ will not allow any automatic conversion. In the following example, the procedure "routine" must be called with the argument BIG or SMALL, but TRUE, FALSE, 0, etc., are not allowed: class opt1 { public: int value; opt1(int m, int) {value = m;} }; const opt1 BIG(0, 0); const opt1 SMALL(1, 0); const int FALSE = 0; const int TRUE = 1; extern void routine(opt1); main() { routine(BIG); routine(SMALL); routine(TRUE); routine(0); } The last two calls to routine generate the following error messages: CC options.c: "options.c", line 19: error: cannot make a opt1 from a const int "options.c", line 20: error: cannot make a opt1 from a zero 2 errors