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









"cal" <callumenator gmail.com> 