| Thread overview | |||||||
|---|---|---|---|---|---|---|---|
| 
 | 
| August 26, 2012opUnary overloading | ||||
|---|---|---|---|---|
| 
 | ||||
| 
I have a struct wrapping a union of an int and a float, and want to overload opUnary for this struct:
struct Value
{
    enum Type {
        INT, FLOAT
    }
    Type type;
    union {
        int i;
        float f;
    }
    this(int _i) {
        i = _i;
        type = Type.INT;
    }
    this(float _f) {
        f = _f;
        type = Type.FLOAT;
    }
    auto opUnary(string s)() if (s == "-") {
        if (type == Type.INT)
            return -i;
        if (type == Type.FLOAT) // If i comment this out, I get an int back
            return -f;          // as expected
        assert(0);
    }
}
Value v1 = Value(25);
assert(v1.type == Value.Type.INT);
auto neg = -v1;
writeln(typeof(neg).stringof); // this returns float, when it should return int
The part I don't understand is this: in the opUnary method, if I comment out the second if conditional (if (type == Type.FLOAT)) then when doing the negation on v1 I get an INT as expected. If I don't comment this code out, I get a float.
When commented out, I get back -25 as an int, which i expect. When not commented out, I get back -nan, which suggests to me that it is returning the (uninitialized) float from the union, not simply giving me back the int as a float.
Could someone explain this?
 | ||||
| August 26, 2012Re: opUnary overloading | ||||
|---|---|---|---|---|
| 
 | ||||
| Posted in reply to cal | I should clarify that I realize the auto cannot be used at runtime to select the return type - I just don't understand why the float part of the union is returned at runtime, instead of the int converted to whatever the compiler determines the return-type of opUnary to be. | |||
| August 26, 2012Re: opUnary overloading | ||||
|---|---|---|---|---|
| 
 | ||||
| Posted in reply to cal | On 08/26/2012 10:33 PM, cal wrote: > > I have a struct wrapping a union of an int and a float, and want to > overload opUnary for this struct: > > struct Value > { > enum Type { > INT, FLOAT > } > > Type type; > > union { > int i; > float f; > } > > this(int _i) { > i = _i; > type = Type.INT; > } > > this(float _f) { > f = _f; > type = Type.FLOAT; > } > > auto opUnary(string s)() if (s == "-") { > if (type == Type.INT) > return -i; > if (type == Type.FLOAT) // If i comment this out, I get an int > back > return -f; // as expected > assert(0); > } > } > > Value v1 = Value(25); > assert(v1.type == Value.Type.INT); > auto neg = -v1; > writeln(typeof(neg).stringof); // this returns float, when it should > return int > > The part I don't understand is this: in the opUnary method, if I comment > out the second if conditional (if (type == Type.FLOAT)) then when doing > the negation on v1 I get an INT as expected. If I don't comment this > code out, I get a float. > > When commented out, I get back -25 as an int, which i expect. When not > commented out, I get back -nan, which suggests to me that it is > returning the (uninitialized) float from the union, not simply giving me > back the int as a float. > > Could someone explain this? > > > Compiler bug. http://d.puremagic.com/issues/ Also see: http://d.puremagic.com/issues/show_bug.cgi?id=8307 I assume the compiler fails to add an implicit conversion node into the AST because at the point where -i is returned, the return type is still assumed to be 'int'. What you are observing is not type coercion, but an x87 FPU stack underflow. | |||
| August 26, 2012Re: opUnary overloading | ||||
|---|---|---|---|---|
| 
 | ||||
| Posted in reply to cal | On 08/26/2012 01:33 PM, cal wrote: > > I have a struct wrapping a union of an int and a float, and want to > overload opUnary for this struct: > > struct Value > { > enum Type { > INT, FLOAT > } > > Type type; > > union { > int i; > float f; > } > > this(int _i) { > i = _i; > type = Type.INT; > } > > this(float _f) { > f = _f; > type = Type.FLOAT; > } > > auto opUnary(string s)() if (s == "-") { > if (type == Type.INT) > return -i; > if (type == Type.FLOAT) // If i comment this out, I get an int back > return -f; // as expected > assert(0); > } > } > > Value v1 = Value(25); > assert(v1.type == Value.Type.INT); > auto neg = -v1; > writeln(typeof(neg).stringof); // this returns float, when it should > return int > > The part I don't understand is this: in the opUnary method, if I comment > out the second if conditional (if (type == Type.FLOAT)) then when doing > the negation on v1 I get an INT as expected. If I don't comment this > code out, I get a float. > > When commented out, I get back -25 as an int, which i expect. When not > commented out, I get back -nan, which suggests to me that it is > returning the (uninitialized) float from the union, not simply giving me > back the int as a float. > > Could someone explain this? opUnary should return Value: Value opUnary(string s)() if (s == "-") { final switch (type) with (Type) { case INT: return Value(-i); case FLOAT: return Value(-f); } } I have also taken advantage of - 'final switch' to obviate the assert(0) - 'with' to simplify syntax (no need to be explicit as in 'Type.INT' anymore) Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html | |||
| August 26, 2012Re: opUnary overloading | ||||
|---|---|---|---|---|
| 
 | ||||
| Posted in reply to Timon Gehr | On Sunday, 26 August 2012 at 20:54:35 UTC, Timon Gehr wrote:
> Also see:
> http://d.puremagic.com/issues/show_bug.cgi?id=8307
>
> I assume the compiler fails to add an implicit conversion node into the
> AST because at the point where -i is returned, the return type is still
> assumed to be 'int'. What you are observing is not type coercion, but
> an x87 FPU stack underflow.
"If there are multiple ReturnStatements, the types of them must match exactly."
Understood, I wasn't doing this.
 | |||
Copyright © 1999-2021 by the D Language Foundation
  Permalink
Permalink Reply
Reply