3) If I assign a float to an integer, then I get the error: "conversion of integer to float loses precision" which isn't quite what you meant to say. More particularly, for float conversions I would expect:
* Conversion from a float holding an integer value that's within the range of the target type to always succeed. * Conversion from a float holding a non-integral value to conditionally succeed (with trunction) depending on the policy in effect. * Conversion *to* a float may also fail if the integer is outside the range of the float (no checking may be required if the number of bits in the integer is less than the number of bits in the float).
my implementation of this is sort of an afterthought and needs attention. It's similar to the case as above. It's not clear what I want to do - even to me.
int i = 1.0
I wonder what we're really doing here. In C++/C i get it. But when I write in C++ the value 1.0 I'm mean a value which in some sense approximates 1.0. I think it's mistake.
int j = 1.5
This is pretty clear to me. The fundamental premise of the library would be stated.
"All expressions which change the arithmetic value are considered errors"
On the other hand, I might be OK with
int k = floor(1.5);
I'm still sorting out how I feel about going back and forth between floats and integers.
Nod.
It's fairly common to see in floating point code, something like:
int integer_part = my_float;
double fractional_part = my_float - integer_part;
which is of course pretty seriously unsafe :(
Casting to a safe<int> to ensure there is no overflow would simplify a
lot of error checking code.
Now we could insist that my_float is passed through
floor/ceil/trunc/round before the conversion, and that's OK by me even
though the function call is superfluous in this instance, but since we
don't know where a floating point value has been, we can't actually
allow that, without also allowing assignment from any old float (albeit
with runtime checking).
BTW for the record, Boost.Math uses itrunc/ltrunc/lltrunc for this
operation which throws when the float is too large for the target type.
Lots of ways to tackle this, I just wanted you to be aware that there
are genuine use cases where float-interoperability is useful and needed.
I guess there are several possible solutions:
Policies: we have 3 levels of checks:
* Permissive, allow all conversions from float and truncate (as long as
the truncated value is in range).
* Strict, only allow conversion from in-range integral values. Values
with fractional parts throw.
* Never: static assert on any attempt to convert from float.
An alternative is to use external functions, lets say we have:
template