December 06, 2013
>> The best that could be done would arguably be to simply do the
>> comparison the 'right' way. E.g. static assert(-1 < 0u).
>
> What's the 'right' way? assert(-1 < uint.max) will always fail because
> no matter whether you convert to int or uint, the comparison simply
> cannot be carried out at the machine code level.

But the compiler should be able to do such things at compile time.
If you compare an unsigned variable with a negative literal,
"-1 < x" or "x > -1": the whole expression can be rewritten to "true",
"-1 == x" or "-1 > x" or "-1 >= x" etc. can be rewritten to "false".
This is not only no performance problem but instead extremely efficient!
December 06, 2013
On Friday, 6 December 2013 at 11:56:35 UTC, Jonathan M Davis wrote:
> There's no such thing as standard warnins in C. What gets warned about depends
> entirely on the compiler and what it's settings are.
You are 100% right, I was speaking out of my mind.

Anyway, I still don't understand the rationale behind allowing those comparisons in C in the first place, but I guess I will never know :P
December 06, 2013
On 12/06/2013 02:06 AM, H. S. Teoh wrote:
> On Thu, Dec 05, 2013 at 10:06:55PM +0100, Timon Gehr wrote:
>> On 12/05/2013 07:26 PM, Jonathan M Davis wrote:
>>> The best that could be done would be to warn about the comparison
>>> or to make it an error.
>>>
>>> http://d.puremagic.com/issues/show_bug.cgi?id=259
>>> ...
>>
>> The best that could be done would arguably be to simply do the
>> comparison the 'right' way. E.g. static assert(-1 < 0u).
>
> What's the 'right' way? assert(-1 < uint.max) will always fail because
> no matter whether you convert to int or uint, the comparison simply
> cannot be carried out at the machine code level. The only way you can
> get a sane answer out of this is if the compiler translates it into:
>
> 	if (intVar < 0 || cast(uint)intVar < uintVar) { ... }
>
>
> T
>

Yup, that's the 'right' way.
December 06, 2013
On Thursday, 5 December 2013 at 17:15:39 UTC, Steve Teale wrote:
> Here I feel like a beginner, but it seems very unfriendly:
>
> import std.stdio;
>
> struct ABC
> {
>    double a;
>    int b;
>    bool c;
> }
>
> ABC[20] aabc;
>
> void foo(int n)
> {
>    writefln("n: %d, aabc.length: %d", n, aabc.length);
>    if (n < aabc.length)
>       writeln("A");
>    else
>       writeln("B");
> }
>
> void main(string[] args)
> {
>    int n = -1;
>    foo(n);
> }
>
Oh my, what a hornet's nest!

I'd settle for an error that said that it's not permissible to compare a negative integer with a size_t. But almost any way you go is ugly.

Thank you all. I feel less like a beginner now ;=)
December 06, 2013
On Thursday, 5 December 2013 at 18:26:48 UTC, Jonathan M Davis wrote:
> To be fair, you can't solve the problem automatically. It's fundamentally
> wrong to compare signed and unsigned values, and doing either the conversion
> to unsigned or to signed could be wrong (or both could be wrong), depending on
> the values.

*Actually*... that's not exactly true.

std.algorithm.max and std.algorithm.min actually do it perfectly well.

It is completely feaseable to imagine having an:
std.functional.less(T, U)(T t, U u){}

Which could work for *any* (compatible) type, including those with mixed signed-ness.

The only "issue" is that if the signs *are* mixed, the comparison is a *bit* more costly. It involved *two* comparisons, and a boolean condition:
https://github.com/D-Programming-Language/phobos/blob/ab34fb92addca61755474df04a0d0d6e0f1148a2/std/algorithm.d#L6698

Truth be told, "a < b" could work correctly 100% of the time, no question asked, if the *language* wanted to. The (2) problems would be:
1) Breaks backward compatibility with C and C++.
2) Higher (and hidden) comparison costs.

Try to convince Walter that these are worth it XD !
December 06, 2013
On Friday, December 06, 2013 18:28:09 monarch_dodra wrote:
> On Thursday, 5 December 2013 at 18:26:48 UTC, Jonathan M Davis
> 
> wrote:
> > To be fair, you can't solve the problem automatically. It's
> > fundamentally
> > wrong to compare signed and unsigned values, and doing either
> > the conversion
> > to unsigned or to signed could be wrong (or both could be
> > wrong), depending on
> > the values.
> 
> *Actually*... that's not exactly true.
> 
> std.algorithm.max and std.algorithm.min actually do it perfectly well.
> 
> It is completely feaseable to imagine having an:
> std.functional.less(T, U)(T t, U u){}
> 
> Which could work for *any* (compatible) type, including those
> with mixed signed-ness.
> 
> The only "issue" is that if the signs *are* mixed, the comparison
> is a *bit* more costly. It involved *two* comparisons, and a
> boolean condition:
> https://github.com/D-Programming-Language/phobos/blob/ab34fb92addca61755474d
> f04a0d0d6e0f1148a2/std/algorithm.d#L6698
> 
> Truth be told, "a < b" could work correctly 100% of the time, no
> question asked, if the *language* wanted to. The (2) problems
> would be:
> 1) Breaks backward compatibility with C and C++.
> 2) Higher (and hidden) comparison costs.
> 
> Try to convince Walter that these are worth it XD !

Ah, good point. I was assuming that you would just doing a straight up comparison, in which case, you have to pick either signed or unsigned, whereas if you can convert both ways and do both comparisons, that does change things a bit. But still, I wouldn't expect Walter to ever agree to something like that, and honestly, I think that making it an error and requiring the programmer to deal with it is still a better option anyway. They can then use a function to do the comparison that you're describing when they actually want that and thus only incur the cost when that's what they really want. The key is just to make sure that you don't silently do the single conversion and comparison and end up with a bug. How to best do the comparison depends on what you're trying to do.

- Jonathan M Davis
1 2 3
Next ›   Last »