On 19/08/2022 12:25, Frederick Virchanza Gotham wrote:
> I'm programming a microcontroller in C++ (the Arduino Due sam3x8e).
>
> I'm playing around with 16-Bit unsigned integers. Sometimes the additions and multiplications overflow, and sometimes subtraction underflows.
>
> The best way to handle this for my particular project is:
> (1) If addition or multiplication overflows, yield UINT_MAX
> (2) If subtraction underflows, yield 0
>
> This morning I wrote a class which is intended to be used as follows:
>
> int main(void)
> {
> uint16_t i = 30000u;
>
> Clamp(i) *= 3u;
>
> cout << i << endl;
> }
>
> So the above program prints "65535".
>
> Here's the header file I wrote this morning, please tell me how you'd improve upon it:
That class and its usage does not feel right to me - you are making a
class that is a wrapper around a reference to an integer object, and
then performing arithmetic on the reference wrapper. I'd feel happier
with an interface like :
int main(void)
{
saturating<uint16_t> i = 30000;
i *= 3;
cout << i << endl;
}
That will also work far better when you have more complex expressions.
Also, your multiplication function is going to be painfully inefficient.
Avoid division whenever possible. It's better to use larger sized
multiplication and check for overflow, or __builtin_mul_overflow_p and
related functions if your compiler supports them. A division-based
solution might be okay as a fallback if nothing better is available, but
don't make it your first choice.