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