Thread overview
How use "toHash" without cast
Jun 20, 2012
Namespace
Jun 20, 2012
Namespace
Jun 21, 2012
Jonathan M Davis
Jun 21, 2012
Namespace
Jun 21, 2012
Jonathan M Davis
Jun 21, 2012
Namespace
June 20, 2012
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?
June 20, 2012
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
June 20, 2012
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...
June 21, 2012
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
June 21, 2012
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
June 21, 2012
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
June 21, 2012
> 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.
June 21, 2012
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
June 21, 2012
I see, a bit confusing but I think I understand.
Thank you. :)