Jump to page: 1 24  
Page
Thread overview
Cast Object - get null
Apr 18, 2012
Namespace
Apr 18, 2012
Jonathan M Davis
Apr 18, 2012
Namespace
Apr 18, 2012
Jonathan M Davis
Apr 18, 2012
Namespace
Apr 18, 2012
Namespace
Apr 18, 2012
Jonathan M Davis
Apr 18, 2012
Namespace
Apr 18, 2012
Namespace
Apr 18, 2012
Namespace
Apr 18, 2012
Jonathan M Davis
Apr 18, 2012
Namespace
Apr 18, 2012
Namespace
Apr 18, 2012
Jonathan M Davis
Apr 19, 2012
Jonathan M Davis
Apr 19, 2012
Namespace
Apr 19, 2012
Jonathan M Davis
Apr 19, 2012
Namespace
Apr 19, 2012
Jonathan M Davis
Apr 19, 2012
Namespace
Apr 19, 2012
Jonathan M Davis
Apr 19, 2012
Namespace
Apr 19, 2012
Namespace
Apr 19, 2012
Jonathan M Davis
Apr 19, 2012
Namespace
Apr 19, 2012
Jonathan M Davis
Apr 19, 2012
Namespace
Apr 19, 2012
Namespace
Apr 19, 2012
Namespace
Apr 19, 2012
Namespace
Apr 19, 2012
Jakob Ovrum
Apr 19, 2012
Namespace
Apr 19, 2012
Jonathan M Davis
April 18, 2012
override bool opEquals(Object o) const {
        if (o is null) {
		return false;
	}
	
	writeln(o); // write: cast.Vector2D!(float).Vector2D
	
	Vector2D!(T) vec = cast(Vector2D!(T)) o;
	
	writeln(vec); // write: null
        // ...

It seems the cast fail, but the question is: why?

Here my test context:

void main() {
	alias Vector2D!(short) Vector2s;
	alias Vector2D!(float) Vector2f;
	
	Vector2f vf = Vector2f(23, 42);
	
	Vector2s vs = Vector2s(vf);
	
	writefln("vs.x: %d, vs.y: %d", vs.x, vs.y);
	
	Vector2s vs2 = Vector2s(23, 42);
	
	if (vs2 == vf) {
		writeln("equal");
	}
}

Vector2D is my own class. If i compare vs2 with vs it works fine,
but if i compare vs or vs2 with vf, the cast fail and i get a
null-reference. How can i avoid this?
April 18, 2012
On Wednesday, April 18, 2012 18:58:42 Namespace wrote:
> override bool opEquals(Object o) const {
> if (o is null) {
> return false;
> }
> 
> writeln(o); // write: cast.Vector2D!(float).Vector2D
> 
> Vector2D!(T) vec = cast(Vector2D!(T)) o;
> 
> writeln(vec); // write: null
> // ...
> 
> It seems the cast fail, but the question is: why?
> 
> Here my test context:
> 
> void main() {
> alias Vector2D!(short) Vector2s;
> alias Vector2D!(float) Vector2f;
> 
> Vector2f vf = Vector2f(23, 42);
> 
> Vector2s vs = Vector2s(vf);
> 
> writefln("vs.x: %d, vs.y: %d", vs.x, vs.y);
> 
> Vector2s vs2 = Vector2s(23, 42);
> 
> if (vs2 == vf) {
> writeln("equal");
> }
> }
> 
> Vector2D is my own class. If i compare vs2 with vs it works fine, but if i compare vs or vs2 with vf, the cast fail and i get a null-reference. How can i avoid this?

Vector2s and Vector2f are completely unrelated types. Templated types have no relation to one another even if they're generated from the same template unless they have the same template arguments. If you have

class Foo(T)
{
 T value;
}

and you do

auto a = new Foo!int;
auto b = new Foo!float;

it's like you copy and pasted to create two new classes:

class FooInt
{
 int value;
}

class FooFloat
{
 float value;
}

and those classes aren't related at all. They could have a common base class (and do with Object) if you declared them that way

class Foo(T) : Base
{
 T value;
}

and then they could both be cast to the base type, but they can't be cast to each other, because neither is derived from the other.

If you want to be able to cast your Vector2D!int and Vector2D!float types to one another, you're going to need to overload opCast.

- Jonathan M Davis
April 18, 2012
> one another, you're going to need to overload opCast.
>
> - Jonathan M Davis

Thanks for your answer.
I have tried to overload opCast in this way:
U opCast(U)() const {
    return U(this.x, this.y);
}

But then i get this compiler error
cast.d(36): Error: no property 'opCall' for type 'object.Object'
cast.d(299): Error: template instance cast.Vector2D!(short).Vector2D.opCast!(Obj
ect) error instantiating
cast.d(36): Error: no property 'opCall' for type 'object.Object'
cast.d(299): Error: template instance cast.Vector2D!(float).Vector2D.opCast!(Obj
ect) error instantiating

The dokumentation of opCast is very short, did i understand opCast wrong?


April 18, 2012
On Wednesday, April 18, 2012 19:15:21 Namespace wrote:
> > one another, you're going to need to overload opCast.
> > 
> > - Jonathan M Davis
> 
> Thanks for your answer.
> I have tried to overload opCast in this way:
> U opCast(U)() const {
> return U(this.x, this.y);
> }
> 
> But then i get this compiler error
> cast.d(36): Error: no property 'opCall' for type 'object.Object'
> cast.d(299): Error: template instance
> cast.Vector2D!(short).Vector2D.opCast!(Obj
> ect) error instantiating
> cast.d(36): Error: no property 'opCall' for type 'object.Object'
> cast.d(299): Error: template instance
> cast.Vector2D!(float).Vector2D.opCast!(Obj
> ect) error instantiating
> 
> The dokumentation of opCast is very short, did i understand opCast wrong?

You're dealing with a class, so you need to use new. As it stands, you're trying to call an overload static opCall on U, and presumably, you haven't declared one.

Ideally, you'd also have a template constraint restricting the cast to the types that you want to be able to cast to, but since you're dealing with a templated type, that can be a bit tricky. One (somewhat ugly) option would be to do something like

U opCast(U) const
 if(is(Unqual!U == Vector2D!byte) ||
 is(Unqual!U == Vector2D!ubyte) ||
 is(Unqual!U == Vector2D!short) ||
 is(Unqual!U == Vector2D!ushort) ||
 is(Unqual!U == Vector2D!int) ||
 is(Unqual!U == Vector2D!uint) ||
 is(Unqual!U == Vector2D!long) ||
 is(Unqual!U == Vector2D!ulong) ||
 is(Unqual!U == Vector2D!float) ||
 is(Unqual!U == Vector2D!double) ||
 is(Unqual!U == Vector2D!real))
{
 return new U(x, y);
}

Another would be to have an enum on the type indicating that it's an instantiation of your Vector2D template (e.g. isVector2D).

U opCast(U) const
 if(__traits(compiles, U.isVector2D))
{
 return new U(x, y);
}

- Jonathan M Davis
April 18, 2012
I take your first example and the relevant class part looks now like this:
class Vector2D(T) {
public:
	T x;
	T y;

	this() { }

	/**
	*
	*/
	static Vector2D!(T) opCall(U, V)(U x, V y) {
		Vector2D!(T) vec = new Vector2D!(T)();
		vec.x = cast(T) x;
		vec.y = cast(T) y;

		return vec;
	}
	
	/**
	*
	*/
	static Vector2D!(T) opCall(U)(const Vector2D!(U) vec) {
		assert(vec !is null);

		return Vector2D!(T)(vec.x, vec.y);
	}
	
	U opCast(U)() const
		if (is(Unqual!U == Vector2D!byte) ||
			is(Unqual!U == Vector2D!ubyte) ||
			is(Unqual!U == Vector2D!short) ||
			is(Unqual!U == Vector2D!ushort) ||
			is(Unqual!U == Vector2D!int) ||
			is(Unqual!U == Vector2D!uint) ||
			is(Unqual!U == Vector2D!long) ||
			is(Unqual!U == Vector2D!ulong) ||
			is(Unqual!U == Vector2D!float) ||
			is(Unqual!U == Vector2D!double) ||
			is(Unqual!U == Vector2D!real))
	{
		U v = new U(this.x, this.y);
	}

As you see i have a static opCall.
But now i get this compiler errors:
cast.d(309): Error: template instance opCast!(Object) opCast!(Object) does not m
atch template declaration opCast(U) if (is(Unqual!(U) == Vector2D!(byte)) || is(
Unqual!(U) == Vector2D!(ubyte)) || is(Unqual!(U) == Vector2D!(short)) || is(Unqu
al!(U) == Vector2D!(ushort)) || is(Unqual!(U) == Vector2D!(int)) || is(Unqual!(U
) == Vector2D!(uint)) || is(Unqual!(U) == Vector2D!(long)) || is(Unqual!(U) == V
ector2D!(ulong)) || is(Unqual!(U) == Vector2D!(float)) || is(Unqual!(U) == Vecto
r2D!(double)) || is(Unqual!(U) == Vector2D!(real)))
cast.d(309): Error: function expected before (), not vs2.opCast!(Object) of type
 void
cast.d(309): Error: template instance opCast!(Object) opCast!(Object) does not m
atch template declaration opCast(U) if (is(Unqual!(U) == Vector2D!(byte)) || is(
Unqual!(U) == Vector2D!(ubyte)) || is(Unqual!(U) == Vector2D!(short)) || is(Unqu
al!(U) == Vector2D!(ushort)) || is(Unqual!(U) == Vector2D!(int)) || is(Unqual!(U
) == Vector2D!(uint)) || is(Unqual!(U) == Vector2D!(long)) || is(Unqual!(U) == V
ector2D!(ulong)) || is(Unqual!(U) == Vector2D!(float)) || is(Unqual!(U) == Vecto
r2D!(double)) || is(Unqual!(U) == Vector2D!(real)))
cast.d(309): Error: function expected before (), not vf.opCast!(Object) of type
void

It seems that opCast and opEquals don't like each other.
Line 309 is
if (vs2 == vf) {
April 18, 2012
Sorry, "U v = new U(this.x, this.y);" means "U v = U(this.x, this.y);"
I tested it with static opCall and also with a normal constructor this(T x, T y)
April 18, 2012
On Wednesday, April 18, 2012 19:37:25 Namespace wrote:
> I take your first example and the relevant class part looks now
> like this:
> class Vector2D(T) {
> public:
> T x;
> T y;
> 
> this() { }
> 
> /**
> *
> */
> static Vector2D!(T) opCall(U, V)(U x, V y) {
> Vector2D!(T) vec = new Vector2D!(T)();
> vec.x = cast(T) x;
> vec.y = cast(T) y;
> 
> return vec;
> }
> 
> /**
> *
> */
> static Vector2D!(T) opCall(U)(const Vector2D!(U) vec) {
> assert(vec !is null);
> 
> return Vector2D!(T)(vec.x, vec.y);
> }
> 
> U opCast(U)() const
> if (is(Unqual!U == Vector2D!byte) ||
> is(Unqual!U == Vector2D!ubyte) ||
> is(Unqual!U == Vector2D!short) ||
> is(Unqual!U == Vector2D!ushort) ||
> is(Unqual!U == Vector2D!int) ||
> is(Unqual!U == Vector2D!uint) ||
> is(Unqual!U == Vector2D!long) ||
> is(Unqual!U == Vector2D!ulong) ||
> is(Unqual!U == Vector2D!float) ||
> is(Unqual!U == Vector2D!double) ||
> is(Unqual!U == Vector2D!real))
> {
> U v = new U(this.x, this.y);
> }
> 
> As you see i have a static opCall.
> But now i get this compiler errors:
> cast.d(309): Error: template instance opCast!(Object)
> opCast!(Object) does not m
> atch template declaration opCast(U) if (is(Unqual!(U) ==
> Vector2D!(byte)) || is(
> Unqual!(U) == Vector2D!(ubyte)) || is(Unqual!(U) ==
> Vector2D!(short)) || is(Unqu
> al!(U) == Vector2D!(ushort)) || is(Unqual!(U) == Vector2D!(int))
> 
> || is(Unqual!(U
> 
> ) == Vector2D!(uint)) || is(Unqual!(U) == Vector2D!(long)) ||
> is(Unqual!(U) == V
> ector2D!(ulong)) || is(Unqual!(U) == Vector2D!(float)) ||
> is(Unqual!(U) == Vecto
> r2D!(double)) || is(Unqual!(U) == Vector2D!(real)))
> cast.d(309): Error: function expected before (), not
> vs2.opCast!(Object) of type
> void
> cast.d(309): Error: template instance opCast!(Object)
> opCast!(Object) does not m
> atch template declaration opCast(U) if (is(Unqual!(U) ==
> Vector2D!(byte)) || is(
> Unqual!(U) == Vector2D!(ubyte)) || is(Unqual!(U) ==
> Vector2D!(short)) || is(Unqu
> al!(U) == Vector2D!(ushort)) || is(Unqual!(U) == Vector2D!(int))
> 
> || is(Unqual!(U
> 
> ) == Vector2D!(uint)) || is(Unqual!(U) == Vector2D!(long)) ||
> is(Unqual!(U) == V
> ector2D!(ulong)) || is(Unqual!(U) == Vector2D!(float)) ||
> is(Unqual!(U) == Vecto
> r2D!(double)) || is(Unqual!(U) == Vector2D!(real)))
> cast.d(309): Error: function expected before (), not
> vf.opCast!(Object) of type
> void
> 
> It seems that opCast and opEquals don't like each other.
> Line 309 is
> if (vs2 == vf) {

1. opCast doesn't do an implict cast. You'll have to cast to get == to work.

2. If you really have a static opCall, then the new isn't necessary.

3. You need to return from opCast. You're just declaring a local variable.

4. You need to import std.traits, or using Unqual will cause the template constraint to fail.

- Jonathan M Davis
April 18, 2012
> 1. opCast doesn't do an implict cast. You'll have to cast to get == to work.
>
> 2. If you really have a static opCall, then the new isn't necessary.
>
> 3. You need to return from opCast. You're just declaring a local variable.
>
> 4. You need to import std.traits, or using Unqual will cause the template
> constraint to fail.
>
> - Jonathan M Davis

1. What have i to cast explicit? I thought that does the overloaded opEquals for me?
2. See my post above.
3. I return with "return U(this.x, this.y);" that is not a local variable, imo.
4. Of course i import it, but it is implicit import if i import std.stdio.

Here my total sourc eto avoid misconceptions: http://codepad.org/fnkyysYu
April 18, 2012
I see i must write

if (vs2 == cast(Vector2s)(vf)) {
	writeln("equal");
}

That is unacceptable. Is this the only possibility?
I thought that opEquals can cast this intern. It would seem that D code isn't so brief as i thought and hoped before.
April 18, 2012
On Wednesday, 18 April 2012 at 19:18:42 UTC, Namespace wrote:
> I see i must write
>
> if (vs2 == cast(Vector2s)(vf)) {
> 	writeln("equal");
> }
>
> That is unacceptable. Is this the only possibility?
> I thought that opEquals can cast this intern. It would seem that D code isn't so brief as i thought and hoped before.

I was wrong, event with
if (vs2 == cast(Vector2s)(vf)) {
it doesn't work.
I get still this compiler error:

cast.d(308): Error: template instance opCast!(Object) opCast!(Object) does not m
atch template declaration opCast(U) if (is(Unqual!(U) == Vector2D!(byte)) || is(
Unqual!(U) == Vector2D!(ubyte)) || is(Unqual!(U) == Vector2D!(short)) || is(Unqu
al!(U) == Vector2D!(ushort)) || is(Unqual!(U) == Vector2D!(int)) || is(Unqual!(U
) == Vector2D!(uint)) || is(Unqual!(U) == Vector2D!(long)) || is(Unqual!(U) == V
ector2D!(ulong)) || is(Unqual!(U) == Vector2D!(float)) || is(Unqual!(U) == Vecto
r2D!(double)) || is(Unqual!(U) == Vector2D!(real)))
cast.d(308): Error: function expected before (), not vs2.opCast!(Object) of type
 void
cast.d(308): Error: template instance opCast!(Object) opCast!(Object) does not m
atch template declaration opCast(U) if (is(Unqual!(U) == Vector2D!(byte)) || is(
Unqual!(U) == Vector2D!(ubyte)) || is(Unqual!(U) == Vector2D!(short)) || is(Unqu
al!(U) == Vector2D!(ushort)) || is(Unqual!(U) == Vector2D!(int)) || is(Unqual!(U
) == Vector2D!(uint)) || is(Unqual!(U) == Vector2D!(long)) || is(Unqual!(U) == V
ector2D!(ulong)) || is(Unqual!(U) == Vector2D!(float)) || is(Unqual!(U) == Vecto
r2D!(double)) || is(Unqual!(U) == Vector2D!(real)))
cast.d(308): Error: function expected before (), not vf.opCast().opCast!(Object)
 of type void
« First   ‹ Prev
1 2 3 4