Martin Sebor <mse...@gmail.com> writes:
> On 10/26/2017 11:52 AM, Richard Sandiford wrote:
>> Martin Sebor <mse...@gmail.com> writes:
>>> For offset_int the default precision is 128-bits.  Making that
>>> the default also for wide_int should be unsurprising.
>>
>> I think it'd be surprising.  offset_int should always be used in
>> preference to wide_int if the precision is known to be 128 bits
>> in advance, and there doesn't seem any reason to prefer the
>> precision of offset_int over widest_int, HOST_WIDE_INT or int.
>>
>> We would end up with:
>>
>>   wide_int
>>   f (const wide_int &y)
>>   {
>>     wide_int x;
>>     x += y;
>>     return x;
>>   }
>>
>> being valid if y happens to have 128 bits as well, and a runtime error
>> otherwise.
>
> Surely that would be far better than the undefined behavior we
> have today.

I disagree.  People shouldn't rely on the above behaviour because
it's never useful.  If y is known to be 128 bits in advance then
the code should be using offset_int instead of wide_int.  And if
y isn't known to be 128 bits in advance, the code is incorrect,
because it needs to cope with precisions other than 128 but doesn't
do so.

The motivation for doing this was to initialise wide_ints to zero,
but the behaviour of f() wouldn't be same as:

   wide_int x = 0 + y;
   return x;

That's always valid, because in an operation involving a wide_int
and a primitive type, the primitive type promotes or demotes
to the same precision as the wide_int.

>> Also, I think it'd be inconsistent to allow the specific case of 0
>> to be assigned by default construction, but not also allow:
>>
>>   wide_int x (0);
>>
>>   wide_int x;
>>   x = 0;
>>
>>   wide_int x;
>>   x = 1;
>>
>> etc.  And wide_int wasn't intended for that use case.
>
> Then perhaps I don't fully understand wide_int.  I would expect
> the above assignments to also "just work" and I can't imagine
> why we would not want them to.  In what way is rejecting
> the above helpful when the following is accepted but undefined?
>
>    wide_int f ()
>    {
>      wide_int x;
>      x += 0;
>      return x;
>    }

Well, it compiles, but with sufficiently good static analysis
it should trigger a warning.  (GCC might not be there yet,
but these things improve.)  As mentioned above:

  wide_int f ()
  {
    wide_int x = ...;
    x += 0;
    return x;
  }

(or some value other than 0) is well-defined because the int
promotes to whatever precision x has.

The problem with the examples I gave was that wide_int always needs
to have a precision and nothing in that code says what the precision
should be.  The "right" way of writing it would be:

   wide_int x = wi::shwi (0, prec);

   wide_int x;
   x = wi::shwi (0, prec);

   wide_int x;
   x = wi::shwi (1, prec);

where prec specifies the precision of the integer.

Thanks,
Richard

Reply via email to