Thread overview | |||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 18, 2012 Cast Object - get null | ||||
---|---|---|---|---|
| ||||
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 Re: Cast Object - get null | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | 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 Re: Cast Object - get null | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | > 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 Re: Cast Object - get null | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | 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 Re: Cast Object - get null | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | 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 Re: Cast Object - get null | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | 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 Re: Cast Object - get null | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | 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 Re: Cast Object - get null | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | > 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 Re: Cast Object - get null | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | 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 Re: Cast Object - get null | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | 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
|
Copyright © 1999-2021 by the D Language Foundation