Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 05, 2002 type conversions | ||||
---|---|---|---|---|
| ||||
These are a bit weird in D: strings we're already discussing, now I'd like to point on the others. This time, it's about int <-> float conversions. I came over this when I was writing the math module. Suppose the abs function: long abs(long n) { return n > 0 ? n : -n; } extended abs(extended n) { // uses inline assembler for FPU's FABS asm { ... } } One for integers, one for floats. Now I write: x = abs(123); And get a compiler error! The problem is, 123 is of type int, and can be converted to both long and extended. So, the call is ambiguous. This can be solved by writing 123L, thus explicitly stating that constant is long, but what about variables? int x; x = abs(cast(long) x); // looks weird, no? Moreover, the same applies to floats: x = abs(123.456); 123.456 is double, and can be converted to both long and extended - ambiguity again, and program fails to compile. You have to: x = abs(cast(extended) 123.456); Of course, one can overload the function for ints and doubles, but don't forget there are also byte, short, ubyte, ushort, uint, ulong and float... well, you get the idea. I guess nobody wants to write all these one-line wrappers just to let user pass argument of any type to your function - probably, the compiler should take care of it. Any ideas? |
April 05, 2002 Re: type conversions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in message news:a8kumf$vgd$1@digitaldaemon.com... > Of course, one can overload the function for ints and doubles, > but don't forget there are also byte, short, ubyte, ushort, > uint, ulong and float... well, you get the idea. I guess nobody > wants to write all these one-line wrappers just to let > user pass argument of any type to your function - probably, > the compiler should take care of it. It will be implicitly converted if you have just one function. But when you have multiple functions, and the call doesn't match exactly one, it should return an error. Otherwise, we fall into the C++ quagmire with a long list of such complicated rules about which one is a "better" fit that it just isn't clear what is happening anymore. |
April 06, 2002 Re: type conversions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> wrote in message news:a8lbqc$1d7s$2@digitaldaemon.com... > It will be implicitly converted if you have just one function. But when you > have multiple functions, and the call doesn't match exactly one, it should return an error. Otherwise, we fall into the C++ quagmire with a long list of such complicated rules about which one is a "better" fit that it just isn't clear what is happening anymore. It doesn't seem that it would be better. Some set of rules is still needed, IMO. Something like this: - any int can be casted to any other int (bit is an int), difficulty 1 - any float can be casted to any other float, difficulty 1 - any int can be casted to any float, difficulty 2 - any float can be casted to any int, difficulty 2 Compiler tries to minimize conversion difficulty when resolving ambiguity. So, whenever you pass an int literal, it will _first_ look for functions taking long, short, byte etc. Only then it tries floats. This means you could supply just two versions of every function: long foo(long) { ... } extended foo(extended) { ... } Now, any int type will be converted to foo, since it's "easier" than converting to extended, and every float will be converted to extended, since it's easier than converting to long. |
April 06, 2002 Re: type conversions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in message news:a8lrq4$25k7$2@digitaldaemon.com... > "Walter" <walter@digitalmars.com> wrote in message news:a8lbqc$1d7s$2@digitaldaemon.com... > > It will be implicitly converted if you have just one function. But when > you > > have multiple functions, and the call doesn't match exactly one, it should > > return an error. Otherwise, we fall into the C++ quagmire with a long list > > of such complicated rules about which one is a "better" fit that it just isn't clear what is happening anymore. > It doesn't seem that it would be better. Some set of rules is still needed, IMO. Something like this: I understand what you mean and the motivation behind it. They're good reasons. But I want to try the three level system of one match, exact match, or ambiguous. |
April 06, 2002 Re: type conversions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> wrote in message news:a8m5hc$2icj$1@digitaldaemon.com... > I understand what you mean and the motivation behind it. They're good reasons. But I want to try the three level system of one match, exact match, > or ambiguous. Then, for your system, which is the correct way to define a function which has two distinct versions for floats and ints, and is able to take arguments of any appropriate type: float, double, extended for float version, and byte, ubyte, short, ushort, int, uint, long, ulong for int version? Do you suggest to write wrappers for every possible case? |
April 06, 2002 Re: type conversions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in message news:a8mkdf$na9$1@digitaldaemon.com... > "Walter" <walter@digitalmars.com> wrote in message news:a8m5hc$2icj$1@digitaldaemon.com... > > > I understand what you mean and the motivation behind it. They're good reasons. But I want to try the three level system of one match, exact > match, > > or ambiguous. > > Then, for your system, which is the correct way to define a function which has two distinct versions for floats and ints, and is able to take arguments of any appropriate type: float, double, extended for float version, and byte, ubyte, short, ushort, int, uint, long, ulong for int version? Do you suggest to write wrappers for every possible case? > > Why isn't there a distinction between integral types and floating point types that is stronger than just typea != typeb? byte, short, int, long etc are all integral types, float, double and extended are floating point types. How about this: integral abs(integral n) { return n > 0 ? n : -n; } floating abs(floating n) { // uses inline assembler for FPU's FABS asm { ... } } Where the compiler will interpret any argument that fits a category as an exact match. Implementation of the function will always take the largest size available on the platform for that type category, making all smaller sizes 'fit'. This might also work for char and wchar: character upcase (character c) { // ... } Where character is the category into which all char-types fall, 8, 16 or 32 bit's. Just an idea... :) -- Stijn OddesE_XYZ@hotmail.com http://OddesE.cjb.net _________________________________________________ Remove _XYZ from my address when replying by mail |
April 06, 2002 Re: type conversions | ||||
---|---|---|---|---|
| ||||
Posted in reply to OddesE | "OddesE" <OddesE_XYZ@hotmail.com> wrote in message news:a8n4jq$19iu$1@digitaldaemon.com... > How about this: ... > Where the compiler will interpret any > argument that fits a category as an exact match. > Implementation of the function will always > take the largest size available on the platform > for that type category, making all smaller > sizes 'fit'. Isn't it simplier to just use "long" and "extended" (since they are always the largest, on any platform)? |
April 06, 2002 Re: type conversions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in message news:a8mkdf$na9$1@digitaldaemon.com... > Then, for your system, which is the correct way to define a function which has two distinct versions for floats and ints, and is able to take arguments of any appropriate type: float, double, extended for float version, and byte, ubyte, short, ushort, int, uint, long, ulong for int version? Do you suggest to write wrappers for every possible case? For the abs() case, I'd just do abs(long) for integral types, and fabs(extended) for floating point types. |
April 06, 2002 Re: type conversions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> wrote in message news:a8naiu$1fr8$1@digitaldaemon.com... > For the abs() case, I'd just do abs(long) for integral types, and > fabs(extended) for floating point types. So: min and fmin max and fmax avg and favg ... Then what's the point of function overloading? Seems we're back to C times... |
April 07, 2002 Re: type conversions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in message news:a8njrd$1qjh$1@digitaldaemon.com... > "Walter" <walter@digitalmars.com> wrote in message news:a8naiu$1fr8$1@digitaldaemon.com... > > For the abs() case, I'd just do abs(long) for integral types, and > > fabs(extended) for floating point types. > So: > min and fmin > max and fmax > avg and favg > ... > Then what's the point of function overloading? Seems we're back > to C times... I'm of the curmudgeonly opinion that function overloading should be used sparingly and that if used, then the argument types should match exactly. I've spent too many hours trying to get the "best" match idea working right in C++. I've run into too much code that was hard to figure out which function was getting called due to subtleties of the "best" match algorithm. It's not worth it. With abs() and fabs(), you only have two functions to handle all the arithmetic types. It's not so bad <g>. |
Copyright © 1999-2021 by the D Language Foundation