## D - type conversions

• Pavel Minayev (34/34) Apr 05 2002 These are a bit weird in D: strings we're already discussing,
• Walter (7/13) Apr 05 2002 It will be implicitly converted if you have just one function. But when ...
• Pavel Minayev (18/23) Apr 05 2002 you
• Walter (7/17) Apr 05 2002 should
• Pavel Minayev (9/12) Apr 06 2002 match,
• OddesE (37/49) Apr 06 2002 Why isn't there a distinction between integral types
• Pavel Minayev (5/12) Apr 06 2002 ...
• OddesE (20/32) Apr 07 2002 But then you keep the problem that it
• Matthew Wilson (8/44) May 06 2002 I kind of like this idea, but isn't it very much like templates & traits...
• Walter (4/10) Apr 06 2002 For the abs() case, I'd just do abs(long) for integral types, and
• Pavel Minayev (9/11) Apr 06 2002 So:
• Walter (10/21) Apr 06 2002 I'm of the curmudgeonly opinion that function overloading should be used
• Stephen Fuld (8/17) Apr 06 2002 Worse than that, since you can compare characters for greater than, etc....
"Pavel Minayev" <evilone omen.ru> writes:
```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?
```
Apr 05 2002
"Walter" <walter digitalmars.com> writes:
```"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.
```
Apr 05 2002
"Pavel Minayev" <evilone omen.ru> writes:
```"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.
```
Apr 05 2002
"Walter" <walter digitalmars.com> writes:
```"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.
```
Apr 05 2002
"Pavel Minayev" <evilone omen.ru> writes:
```"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?
```
Apr 06 2002
"OddesE" <OddesE_XYZ hotmail.com> writes:
```"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.

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
_________________________________________________
```
Apr 06 2002
"Pavel Minayev" <evilone omen.ru> writes:
```"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a8n4jq\$19iu\$1 digitaldaemon.com...

...
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)?
```
Apr 06 2002
"OddesE" <OddesE_XYZ hotmail.com> writes:
```"Pavel Minayev" <evilone omen.ru> wrote in message
news:a8n8c3\$1db8\$1 digitaldaemon.com...
"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a8n4jq\$19iu\$1 digitaldaemon.com...

...
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)?

But then you keep the problem that it
isn't an exact match. With type
categories the programmer could
explicitly state that he allows all
types in the category to be used and
that he expects that behaviour.

Any integer type would always be a
valid 'exact match' with any integral
argument. Only if there where a function
that was an exact match based on type
instead of type category, that function

--
Stijn
OddesE_XYZ hotmail.com
http://OddesE.cjb.net
_________________________________________________
```
Apr 07 2002
"Matthew Wilson" <mwilson nextgengaming.com> writes:
```I kind of like this idea, but isn't it very much like templates & traits.

If Walter would be interested in incorporating a (designed from the ground
up, hence) better template implementation than has C++ (resulting in all the
arcane wangles we have to do to get traits to manipulate type categories,
etc.), then I think the appeal of D would widen very quickly (not that it

"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a8p5km\$12d5\$1 digitaldaemon.com...
"Pavel Minayev" <evilone omen.ru> wrote in message
news:a8n8c3\$1db8\$1 digitaldaemon.com...
"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a8n4jq\$19iu\$1 digitaldaemon.com...

...
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)?

But then you keep the problem that it
isn't an exact match. With type
categories the programmer could
explicitly state that he allows all
types in the category to be used and
that he expects that behaviour.

Any integer type would always be a
valid 'exact match' with any integral
argument. Only if there where a function
that was an exact match based on type
instead of type category, that function

--
Stijn
OddesE_XYZ hotmail.com
http://OddesE.cjb.net
_________________________________________________

```
May 06 2002
"Walter" <walter digitalmars.com> writes:
```"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.
```
Apr 06 2002
"Pavel Minayev" <evilone omen.ru> writes:
```"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
...

to C times...
```
Apr 06 2002
"Walter" <walter digitalmars.com> writes:
```"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
...
to C times...

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>.
```
Apr 06 2002
```"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
...

Worse than that, since you can compare characters for greater than, etc. it
seems reasonable to allow max and min on them as well.  Now you have three
types to declare for those.

--
- Stephen Fuld
e-mail address disguised to prevent spam
```
Apr 06 2002
"Pavel Minayev" <evilone omen.ru> writes:
```"Stephen Fuld" <s.fuld.pleaseremove att.net> wrote in message
news:a8pt6h\$2g47\$1 digitaldaemon.com...

Worse than that, since you can compare characters for greater than, etc.

it
seems reasonable to allow max and min on them as well.  Now you have three
types to declare for those.

If I recall it correctly, characters are castable to ints, so the integer
version would be used by the compiler.
```
Apr 07 2002