www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How use "toHash" without cast

reply "Namespace" <rswhite4 googlemail.com> writes:
hello, iI have written a template vector class. Now I need to 
rewrite the tohash function in dependence to the coords. But i 
have no clue because it doesn't allow any casts or convertions, 
because its a  trusted method.
Because of that i cannot override toHash for float, real or 
double.
Any ideas?
Jun 20 2012
next sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 21-06-2012 00:31, Namespace wrote:
 hello, iI have written a template vector class. Now I need to rewrite
 the tohash function in dependence to the coords. But i have no clue
 because it doesn't allow any casts or convertions, because its a
  trusted method.
 Because of that i cannot override toHash for float, real or double.
 Any ideas?

I don't really understand the problem. I think you need to show some code. trusted doesn't actually affect whether you can cast or convert anything. -- Alex Rønne Petersen alex lycus.org http://lycus.org
Jun 20 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 21-06-2012 03:13, Jonathan M Davis wrote:
 On Thursday, June 21, 2012 00:43:49 Namespace wrote:
 That is my Code:

 [code]
 class Vector2D(T) {
 private:
 static Vector2D!(T) CastFromObject(Object o) {
 import std.typetuple;

 foreach (Type; TypeTuple!(byte, ubyte, short, ushort, int,
 uint, long, ulong, float, double, real)) {
 if (auto vec = cast(Vector2D!(Type)) o) {
 return cast(Vector2D!(T)) vec;
 }
 }

 return null;
 }

 public:
 T x;
 T y;

 this(T x, T y) {
 this.x = x;
 this.y = y;
 }

 static Vector2D!(T) opCall(T x, T y) {
 return new Vector2D!(T)(x, y);
 }

 float Summe() const pure nothrow {
 return this.x + this.y;
 }

 override bool opEquals(Object o) const {
 if (o is null) {
 debug {
 writeln("Object is null ;)");
 }

 return false;
 }

 const Vector2D!(T) vec = CastFromObject(o);

 if (vec is this) {
 return true;
 }

 return (vec.x == this.x)&&  (vec.y == this.y);
 }

 override hash_t toHash() const pure nothrow {
 return this.x + this.y;
 }

 override int opCmp(Object o) const {
 if (o is null) {
 return -1;
 }

 const Vector2D vec = CastFromObject(o);

 if (vec is this) {
 return 0;
 }

 if (this.Summe()>  vec.Summe()) {
 return 1;
 }

 if (this.Summe()<  vec.Summe()) {
 return -1;
 }

 return 0;
 }

 override string toString() const {
 return "Vector2D!(" ~ T.stringof ~ ")(" ~ to!(string)(this.x) ~
 ", " ~ to!(string)(this.y) ~ ")";
 }
 }

 [/code]

 I have dmd 2.059 and with my current version of toHash i get the
 compiler errors, that he cannot implicit convert from float,
 real, double, long and so on to uint.
 I cannot solve the problem with a simple cast or to!uint because
 then he said that casts form float to uint are not allowed or
 that to! isn't trusted and nothrow. I hate such annoying errors...

Eventually, toHash will have to be safe const pure nothrow, but I don't think that the compiler requires that yet (though work was being done on that, so it may). You didn't mark toHash as safe though, so it may be inferring it from Object (I believe that it _has_ been changed so that attributes are now inferred from the base class declarations when overriding). So, toHash may be being inferred as safe. Try marking toHash as trusted. If that doesn't work, then move its implementation into another function which you mark as trusted and have toHash call it (since safe can call trusted but can't do system stuff, unlike trusted). - Jonathan M Davis

It's actually trusted as per the docs. I do not know why DMD infers that to be safe..... In any case, the solution here is this: override hash_t toHash() trusted const pure nothrow { return cast(hash_t)(this.x + this.y); } -- Alex Rønne Petersen alex lycus.org http://lycus.org
Jun 20 2012
parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 21-06-2012 04:30, Alex Rønne Petersen wrote:
 On 21-06-2012 03:13, Jonathan M Davis wrote:
 On Thursday, June 21, 2012 00:43:49 Namespace wrote:
 That is my Code:

 [code]
 class Vector2D(T) {
 private:
 static Vector2D!(T) CastFromObject(Object o) {
 import std.typetuple;

 foreach (Type; TypeTuple!(byte, ubyte, short, ushort, int,
 uint, long, ulong, float, double, real)) {
 if (auto vec = cast(Vector2D!(Type)) o) {
 return cast(Vector2D!(T)) vec;
 }
 }

 return null;
 }

 public:
 T x;
 T y;

 this(T x, T y) {
 this.x = x;
 this.y = y;
 }

 static Vector2D!(T) opCall(T x, T y) {
 return new Vector2D!(T)(x, y);
 }

 float Summe() const pure nothrow {
 return this.x + this.y;
 }

 override bool opEquals(Object o) const {
 if (o is null) {
 debug {
 writeln("Object is null ;)");
 }

 return false;
 }

 const Vector2D!(T) vec = CastFromObject(o);

 if (vec is this) {
 return true;
 }

 return (vec.x == this.x)&& (vec.y == this.y);
 }

 override hash_t toHash() const pure nothrow {
 return this.x + this.y;
 }

 override int opCmp(Object o) const {
 if (o is null) {
 return -1;
 }

 const Vector2D vec = CastFromObject(o);

 if (vec is this) {
 return 0;
 }

 if (this.Summe()> vec.Summe()) {
 return 1;
 }

 if (this.Summe()< vec.Summe()) {
 return -1;
 }

 return 0;
 }

 override string toString() const {
 return "Vector2D!(" ~ T.stringof ~ ")(" ~ to!(string)(this.x) ~
 ", " ~ to!(string)(this.y) ~ ")";
 }
 }

 [/code]

 I have dmd 2.059 and with my current version of toHash i get the
 compiler errors, that he cannot implicit convert from float,
 real, double, long and so on to uint.
 I cannot solve the problem with a simple cast or to!uint because
 then he said that casts form float to uint are not allowed or
 that to! isn't trusted and nothrow. I hate such annoying errors...

Eventually, toHash will have to be safe const pure nothrow, but I don't think that the compiler requires that yet (though work was being done on that, so it may). You didn't mark toHash as safe though, so it may be inferring it from Object (I believe that it _has_ been changed so that attributes are now inferred from the base class declarations when overriding). So, toHash may be being inferred as safe. Try marking toHash as trusted. If that doesn't work, then move its implementation into another function which you mark as trusted and have toHash call it (since safe can call trusted but can't do system stuff, unlike trusted). - Jonathan M Davis

It's actually trusted as per the docs. I do not know why DMD infers that to be safe..... In any case, the solution here is this: override hash_t toHash() trusted const pure nothrow { return cast(hash_t)(this.x + this.y); }

Filed a bug: http://d.puremagic.com/issues/show_bug.cgi?id=8275 -- Alex Rønne Petersen alex lycus.org http://lycus.org
Jun 20 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
That is my Code:

[code]
class Vector2D(T) {
private:
	static Vector2D!(T) CastFromObject(Object o) {
		import std.typetuple;

		foreach (Type; TypeTuple!(byte, ubyte, short, ushort, int, 
uint, long, ulong, float, double, real)) {
			if (auto vec = cast(Vector2D!(Type)) o) {
				return cast(Vector2D!(T)) vec;
			}
		}

		return null;
	}
	
public:
	T x;
	T y;
	
	this(T x, T y) {
		this.x = x;
		this.y = y;
	}
	
	static Vector2D!(T) opCall(T x, T y) {
		return new Vector2D!(T)(x, y);
	}
	
	float Summe() const pure nothrow {
		return this.x + this.y;
	}
	
	override bool opEquals(Object o) const {
		if (o is null) {
			debug {
				writeln("Object is null ;)");
			}

			return false;
		}

		const Vector2D!(T) vec = CastFromObject(o);

		if (vec is this) {
			return true;
		}

		return (vec.x == this.x) && (vec.y == this.y);
	}
	
	override hash_t toHash() const pure nothrow {
		return this.x + this.y;
	}
	
	override int opCmp(Object o) const {
		if (o is null) {
			return -1;
		}

		const Vector2D vec = CastFromObject(o);

		if (vec is this) {
			return 0;
		}

		if (this.Summe() > vec.Summe()) {
			return 1;
		}

		if (this.Summe() < vec.Summe()) {
			return -1;
		}

		return 0;
	}
	
	override string toString() const {
		return "Vector2D!(" ~ T.stringof ~ ")(" ~ to!(string)(this.x) ~ 
", " ~ to!(string)(this.y) ~ ")";
	}
}

[/code]

I have dmd 2.059 and with my current version of toHash i get the 
compiler errors, that he cannot implicit convert from float, 
real, double, long and so on to uint.
I cannot solve the problem with a simple cast or to!uint because 
then he said that casts form float to uint are not allowed or 
that to! isn't trusted and nothrow. I hate such annoying errors...
Jun 20 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, June 21, 2012 00:43:49 Namespace wrote:
 That is my Code:
 
 [code]
 class Vector2D(T) {
 private:
 static Vector2D!(T) CastFromObject(Object o) {
 import std.typetuple;
 
 foreach (Type; TypeTuple!(byte, ubyte, short, ushort, int,
 uint, long, ulong, float, double, real)) {
 if (auto vec = cast(Vector2D!(Type)) o) {
 return cast(Vector2D!(T)) vec;
 }
 }
 
 return null;
 }
 
 public:
 T x;
 T y;
 
 this(T x, T y) {
 this.x = x;
 this.y = y;
 }
 
 static Vector2D!(T) opCall(T x, T y) {
 return new Vector2D!(T)(x, y);
 }
 
 float Summe() const pure nothrow {
 return this.x + this.y;
 }
 
 override bool opEquals(Object o) const {
 if (o is null) {
 debug {
 writeln("Object is null ;)");
 }
 
 return false;
 }
 
 const Vector2D!(T) vec = CastFromObject(o);
 
 if (vec is this) {
 return true;
 }
 
 return (vec.x == this.x) && (vec.y == this.y);
 }
 
 override hash_t toHash() const pure nothrow {
 return this.x + this.y;
 }
 
 override int opCmp(Object o) const {
 if (o is null) {
 return -1;
 }
 
 const Vector2D vec = CastFromObject(o);
 
 if (vec is this) {
 return 0;
 }
 
 if (this.Summe() > vec.Summe()) {
 return 1;
 }
 
 if (this.Summe() < vec.Summe()) {
 return -1;
 }
 
 return 0;
 }
 
 override string toString() const {
 return "Vector2D!(" ~ T.stringof ~ ")(" ~ to!(string)(this.x) ~
 ", " ~ to!(string)(this.y) ~ ")";
 }
 }
 
 [/code]
 
 I have dmd 2.059 and with my current version of toHash i get the
 compiler errors, that he cannot implicit convert from float,
 real, double, long and so on to uint.
 I cannot solve the problem with a simple cast or to!uint because
 then he said that casts form float to uint are not allowed or
 that to! isn't trusted and nothrow. I hate such annoying errors...

Eventually, toHash will have to be safe const pure nothrow, but I don't think that the compiler requires that yet (though work was being done on that, so it may). You didn't mark toHash as safe though, so it may be inferring it from Object (I believe that it _has_ been changed so that attributes are now inferred from the base class declarations when overriding). So, toHash may be being inferred as safe. Try marking toHash as trusted. If that doesn't work, then move its implementation into another function which you mark as trusted and have toHash call it (since safe can call trusted but can't do system stuff, unlike trusted). - Jonathan M Davis
Jun 20 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 It's actually  trusted as per the docs. I do not know why DMD 
 infers that to be  safe.....

 In any case, the solution here is this:

     override hash_t toHash()  trusted const pure nothrow {
         return cast(hash_t)(this.x + this.y);
     }

Yes, it's already trusted. If I write " trusted const pure nothrow" it works fine, but if i write "const pure nothrow" not. Why? I thought the compiler is orientating at the base method which is overriden.
Jun 21 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, June 21, 2012 09:48:52 Namespace wrote:
 It's actually  trusted as per the docs. I do not know why DMD
 infers that to be  safe.....
 
 In any case, the solution here is this:
     override hash_t toHash()  trusted const pure nothrow {
     
         return cast(hash_t)(this.x + this.y);
     
     }

Yes, it's already trusted. If I write " trusted const pure nothrow" it works fine, but if i write "const pure nothrow" not. Why? I thought the compiler is orientating at the base method which is overriden.

Apparently, when you override an trusted method, the method in the derived class is inferred to be safe - which makes sense when you think about it, since the derived class' function hasn't done anything system. If it calls the base class' version, which is trusted, then it can be safe. So, as long as it doesn't do anything system itself, it can be safe. However, since the compiler doesn't infer any attributes from the derived class' function's body (since it's not templated), if you do any system stuff in there, it'll give you a compilation error rather than treating it as system - though that makes sense too, since having a derived class function with worse guarantees than a base class function isn't valid. So, even if the attributes _were_ inferred from the function's body, it would _still_ have to give you an error, since the body would be system when it needed to be at least trusted. http://d.puremagic.com/issues/show_bug.cgi?id=8275 - Jonathan M Davis
Jun 21 2012
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
I see, a bit confusing but I think I understand.
Thank you. :)
Jun 21 2012