So why double to float conversion is implicit ?
Basile B.
b2.temp at gmx.com
Mon Oct 23 21:51:24 UTC 2017
On Saturday, 21 October 2017 at 20:17:12 UTC, NX wrote:
> I was working on some sort of math library for use in graphical
> computing and I wrote something like this:
>
> const float PiOver2 = (atan(1.0) * 4) / 2;
>
> Interestingly enough, I realized that atan() returns double (in
> this case) but wait, it's assigned to a float variable!
> Compiler didn't even emit warnings, let alone errors.
>
> I see no reason as to why would this be legal in this century,
> especially in D.
> So can someone tell me what's the argument against this?
> Why type conversions differ between integral and floating types?
> Why can't I assign a long to an int but it's fine when
> assigning double to float?
>
> I think this is a serious topic and needs clarification.
In the meantime:
---
/**
* Wraps a floating point type that doesn't follow D permissive
float conversion
* rules.
*
* In D, as in C++, implicit conversion from $(D double) to $(D
float) is allowed,
* leading to a possible precision loss. This can't happen when
using this wrapper.
*/
struct CoercionSafeFloat(T)
if (isFloatingPoint!T)
{
private T _value;
alias _value this;
enum antiCoercion =
q{
static assert(V.sizeof <= T.sizeof, "coercion from " ~
V.stringof ~
" to " ~ T.stringof ~ " is not allowed");
};
/// Prevent Coercion from construction.
this(V)(V v) {mixin(antiCoercion); _value = v;}
/// Prevent Coercion from assignation.
void opAssign(V)(V v) {mixin(antiCoercion); _value = v;}
/// Prevent Coercion from operator assignation.
void opOpAssign(string op, V)(V v)
{
mixin(antiCoercion);
mixin("_value " ~ op ~ "= v;");
}
}
///
unittest
{
alias Float = CoercionSafeFloat!float;
alias Double = CoercionSafeFloat!double;
alias Real = CoercionSafeFloat!real;
Float f; Double d; Real r;
import std.math;
static assert(!__traits(compiles, f = (atan(1.0) * 4) / 2));
static assert( __traits(compiles, f = (atan(1.0f) * 4f) /
2f));
static assert(!__traits(compiles, d = (atan(1.0L) * 4L) /
2L));
static assert(__traits(compiles, d = f));
static assert(!__traits(compiles, f = d));
static assert(!__traits(compiles, d = r));
static assert(!__traits(compiles, d += r));
static assert(__traits(compiles, r *= d));
}
---
you can get a safer float type if this is a concern.
More information about the Digitalmars-d
mailing list