digitalmars.D.learn - opUnary overloading
- cal (43/43) Aug 26 2012 I have a struct wrapping a union of an int and a float, and want
- cal (5/5) Aug 26 2012 I should clarify that I realize the auto cannot be used at
- Timon Gehr (9/52) Aug 26 2012 Compiler bug.
- cal (4/13) Aug 26 2012 "If there are multiple ReturnStatements, the types of them must
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (17/59) Aug 26 2012 opUnary should return Value:
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?
Aug 26 2012
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.
Aug 26 2012
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.
Aug 26 2012
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.
Aug 26 2012
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
Aug 26 2012