Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
August 26, 2012 opUnary 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, 2012 Re: 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, 2012 Re: 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, 2012 Re: 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, 2012 Re: 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