bearophile can say "i told you so" (re uint->int implicit conv)
Steven Schveighoffer
schveiguy at yahoo.com
Wed Apr 3 07:43:06 PDT 2013
On Tue, 02 Apr 2013 23:26:54 -0400, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> wrote:
> On 4/2/13 11:10 PM, Steven Schveighoffer wrote:
>> On Tue, 02 Apr 2013 16:32:21 -0400, Walter Bright
>> <newshound2 at digitalmars.com> wrote:
>>
>>> On 4/2/2013 12:47 PM, Andrei Alexandrescu wrote:
>>>> I used to lean a lot more toward this opinion until I got to work on
>>>> a C++
>>>> codebase using signed integers as array sizes and indices. It's an
>>>> pain all over
>>>> the code - two tests instead of one or casts all over, more cases to
>>>> worry
>>>> about... changing the code to use unsigned throughout ended up being
>>>> an
>>>> improvement.
>>>
>>> For example, with a signed array index, a bounds check is two
>>> comparisons rather than one.
>>
>> Why?
>>
>> struct myArr
>> {
>> int length;
>> int opIndex(int idx) { if(cast(uint)idx >= cast(uint)length) throw new
>> RangeError(); ...}
>> }
>>
>> -Steve
>
> As I said - either two tests or casts all over.
But this is not "all over", it's in one place, for bounds checking.
I find that using unsigned int doesn't really hurt much, but it can make
things awkward.
For example, it's better to do addition than subtraction:
for(int i = 0; i < arr.length - 1; ++i)
{
if(arr[i] >= arr[i+1])
throw new Exception("Not sorted!");
}
This has a bug, and is better written as:
for(int i = 0; i + 1 < arr.length; ++i)
These are the kinds of things that can get you into trouble. With a
signed length, then both loops are equivalent, and we don't have that
error.
I'm not sure which is better. It feels to me that if you CAN achieve the
correct performance (even if this means casting), but the default errs on
the side of safety, that might be a better option.
-Steve
More information about the Digitalmars-d
mailing list