Jump to page: 1 2
Thread overview
cannot cast
Apr 28, 2012
Namespace
Apr 28, 2012
Namespace
alias this : cast turns into endless loop
Apr 28, 2012
Namespace
Apr 29, 2012
Jesse Phillips
Apr 29, 2012
Namespace
May 02, 2012
Namespace
May 02, 2012
Namespace
May 03, 2012
Namespace
May 03, 2012
Jonathan M Davis
May 03, 2012
Namespace
May 03, 2012
Chris Cain
May 03, 2012
Namespace
May 03, 2012
Chris Cain
May 03, 2012
Chris Cain
May 03, 2012
Jonathan M Davis
May 03, 2012
sclytrack
May 03, 2012
Simen Kjaeraas
May 03, 2012
Namespace
May 03, 2012
Namespace
April 28, 2012
I finished my Ref/NotNull struct, but i've got a problem:
If i try to cast the class, which should implicit convert to Ref!(Type) with alias this, i get the following error message:
"cannot cast a1.getRef("Ref.d",72u) of type Ref!(A) to type RefTest.Ref.__unittest1.B"

Can someone explain that to me or help me with it?
It seems that alias this replacement isn't smart enough to distinguish, if it has to convert.

[code]
import std.conv : to;

struct Ref(T : Object) {
private:
	 T _obj;

public:
	@disable
	this();// { }

	@disable
	this(typeof(null));// { }

	this(T obj) {
		assert(obj !is null, "Object is null!");

		this._obj = obj;
	}

	@property
	inout(T) access() inout {
		assert(this._obj !is null, "Access: Object is null!");

		return this._obj;
	}

	//alias access this; // print "Stackoverflow" or "recursive expansion"
}

mixin template TRef(T : Object) {
	final Ref!(T) getRef(string file = __FILE__, size_t line = __LINE__) in {
		assert(this !is null, "Object is null! @ " ~ file ~ " in Line " ~ to!(string)(line) ~ ".");
	} body {
		return Ref!(T)(this);
	}
	
	final Ref!(const T) getRef(string file = __FILE__, size_t line = __LINE__) const in {
		assert(this !is null, "Object is null! @ " ~ file ~ " in Line " ~ to!(string)(line) ~ ".");
	} body {
		return Ref!(const T)(this);
	}

	alias getRef this;
}

unittest {

	class A {
		mixin TRef!(A);
	}

	class B : A { }

	class C : B { }

	A a1 = new B();
	A a2 = new C();

	B b1 = cast(B) a1; // line 72
}
April 28, 2012
On Saturday, 28 April 2012 at 14:21:32 UTC, Namespace wrote:
> I finished my Ref/NotNull struct, but i've got a problem:
> If i try to cast the class, which should implicit convert to Ref!(Type) with alias this, i get the following error message:
> "cannot cast a1.getRef("Ref.d",72u) of type Ref!(A) to type RefTest.Ref.__unittest1.B"
>
> Can someone explain that to me or help me with it?
> It seems that alias this replacement isn't smart enough to distinguish, if it has to convert.
>
> [code]
> import std.conv : to;
>
> struct Ref(T : Object) {
> private:
> 	 T _obj;
>
> public:
> 	@disable
> 	this();// { }
>
> 	@disable
> 	this(typeof(null));// { }
>
> 	this(T obj) {
> 		assert(obj !is null, "Object is null!");
>
> 		this._obj = obj;
> 	}
>
> 	@property
> 	inout(T) access() inout {
> 		assert(this._obj !is null, "Access: Object is null!");
>
> 		return this._obj;
> 	}
>
> 	//alias access this; // print "Stackoverflow" or "recursive expansion"
> }
>
> mixin template TRef(T : Object) {
> 	final Ref!(T) getRef(string file = __FILE__, size_t line = __LINE__) in {
> 		assert(this !is null, "Object is null! @ " ~ file ~ " in Line " ~ to!(string)(line) ~ ".");
> 	} body {
> 		return Ref!(T)(this);
> 	}
> 	
> 	final Ref!(const T) getRef(string file = __FILE__, size_t line = __LINE__) const in {
> 		assert(this !is null, "Object is null! @ " ~ file ~ " in Line " ~ to!(string)(line) ~ ".");
> 	} body {
> 		return Ref!(const T)(this);
> 	}
>
> 	alias getRef this;
> }
>
> unittest {
>
> 	class A {
> 		mixin TRef!(A);
> 	}
>
> 	class B : A { }
>
> 	class C : B { }
>
> 	A a1 = new B();
> 	A a2 = new C();
>
> 	B b1 = cast(B) a1; // line 72
> }

Trying to fix it with an opCast in Ref ended in an infinity loop...

April 28, 2012
Trying with
	U opCast(U : Object)() {
		return new U();
	}

work fine. It isn't a solution, but i don't understand why this works and the following not:

	U opCast(U : Object)() {
		return cast(U) this._obj;
	}

I hope really some of you can explain that to me and help me to fix it.
And forgive me the old senseless thread title. ;)
April 29, 2012
On Saturday, 28 April 2012 at 14:21:32 UTC, Namespace wrote:
> I finished my Ref/NotNull struct, but i've got a problem:
> If i try to cast the class, which should implicit convert to Ref!(Type) with alias this, i get the following error message:
> "cannot cast a1.getRef("Ref.d",72u) of type Ref!(A) to type RefTest.Ref.__unittest1.B"

I would consider this a bug:

http://d.puremagic.com/issues/show_bug.cgi?id=8001
April 29, 2012
On Sunday, 29 April 2012 at 14:40:55 UTC, Jesse Phillips wrote:
> On Saturday, 28 April 2012 at 14:21:32 UTC, Namespace wrote:
>> I finished my Ref/NotNull struct, but i've got a problem:
>> If i try to cast the class, which should implicit convert to Ref!(Type) with alias this, i get the following error message:
>> "cannot cast a1.getRef("Ref.d",72u) of type Ref!(A) to type RefTest.Ref.__unittest1.B"
>
> I would consider this a bug:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=8001

Oh, that could explain a lot. Some workaround until now?
May 02, 2012
Can anyone tell me, why the this code

[code]
module RefTest.Ref;

import std.stdio : writeln;
import std.conv : to, toImpl;

T const_cast(T : Object)(const T obj) {
	return cast(T) obj;
}

struct Ref(T : Object) {
private:
	 T _obj;

public:
	@disable
	this();// { }

	@disable
	this(typeof(null));// { }

	this(T obj) {
		assert(obj !is null, "Object is null!");

		this._obj = obj;
	}

	@property
	inout(T) access() inout {
		assert(this._obj !is null, "Access: Object is null!");

		return this._obj;
	}

	//alias access this; // dann kommt "Stackoverflow" oder "recursive expansion"
}

mixin template TRef(T : Object) {
	final Ref!(T) getRef(string file = __FILE__, size_t line = __LINE__) in {
		assert(this !is null, "Object is null! @ " ~ file ~ " in Line " ~ to!(string)(line) ~ ".");
	} body {
		return Ref!(T)(this);
	}
	
	final Ref!(const T) getRef(string file = __FILE__, size_t line = __LINE__) const in {
		assert(this !is null, "Object is null! @ " ~ file ~ " in Line " ~ to!(string)(line) ~ ".");
	} body {
		return Ref!(const T)(this);
	}

	U opCast(U : Object)() {
		return *(cast(U*) &this);
	}

	alias getRef this;
}

unittest {
	bool instanceof(T : Object, U : Object)(const Ref!U obj) {
		//return const_cast(obj.access).toString() == typeid(T).toString();
		const U o = obj.access;

		return const_cast(o).toString() == typeid(T).toString();
	}

	class A {
		mixin TRef!(A);
	}

	class B : A { }

	class C : B { }

	A a1 = new B();
	A a2 = new C();

	assert(instanceof!(A)(a1) == false);
	assert(instanceof!(B)(a1));
	assert(instanceof!(C)(a1) == false);

	writeln(a1);

	B b1 = cast(B) a1;

	writeln(b1);

	writeln();
}
[/code]

fails with:

[quote]
Fehler	3	instantiated from here: instanceof!(A,A)	D:\D\VisualD\Visual Studio 2010\Projects\RefTest\RefTest\Ref.d	76
	
Fehler	2	Error: template instance RefTest.Ref.const_cast!(A) error instantiating	D:\D\VisualD\Visual Studio 2010\Projects\RefTest\RefTest\Ref.d	62
	
Fehler	4	Error: template instance RefTest.Ref.__unittest1.instanceof!(A,A) error instantiating	D:\D\VisualD\Visual Studio 2010\Projects\RefTest\RefTest\Ref.d	76	

Fehler	1	Error: function RefTest.Ref.__unittest1.A.TRef!(A).opCast!(A).opCast () is not callable using argument types ()	D:\D\VisualD\Visual Studio 2010\Projects\RefTest\RefTest\Ref.d	7	
[/quote]

? Sounds like a bug.
May 02, 2012
Other, shorter example:

[code]
import std.stdio, std.traits;

class A {
	int val;

	alias val this;
	
	T opCast(T : Object)() {
		writeln("FOO");
		
		return to!(T)(this);
	}
}

class B : A {

}

T to(T : Object, U : Object)(const U obj) {
	return *(cast(T*) &obj);
}

T const_cast(T)(const T obj) {
	return cast(T) obj;
}

void main () {
	A a = new B();
	a.val = 42;
	
	writefln("a.val: %d", a.val);

	B* b = cast(B*) &a;
	writefln("*b.val: %d", b.val);

	B b1 = to!(B)(a);
	writefln("b1.val: %d", b1.val);
	
	B b2 = cast(B) a;
	writefln("b2.val: %d", b2.val);
	
	const B b3 = cast(B) a;
	
	B b4 = const_cast(b3);
}
[/code]

print:

alias_this_impl.d(24): Error: function alias_this_impl.A.opCast!(B).opCast () is
 not callable using argument types ()
alias_this_impl.d(44): Error: template instance alias_this_impl.const_cast!(B) e
rror instantiating

I'm not very skillful in such "template" stories. Maybe someone can help me?

May 03, 2012
On Wednesday, 2 May 2012 at 22:38:36 UTC, Namespace wrote:
> Other, shorter example:
>
> [code]
> import std.stdio, std.traits;
>
> class A {
> 	int val;
>
> 	alias val this;
> 	
> 	T opCast(T : Object)() {
> 		writeln("FOO");
> 		
> 		return to!(T)(this);
> 	}
> }
>
> class B : A {
>
> }
>
> T to(T : Object, U : Object)(const U obj) {
> 	return *(cast(T*) &obj);
> }
>
> T const_cast(T)(const T obj) {
> 	return cast(T) obj;
> }
>
> void main () {
> 	A a = new B();
> 	a.val = 42;
> 	
> 	writefln("a.val: %d", a.val);
>
> 	B* b = cast(B*) &a;
> 	writefln("*b.val: %d", b.val);
>
> 	B b1 = to!(B)(a);
> 	writefln("b1.val: %d", b1.val);
> 	
> 	B b2 = cast(B) a;
> 	writefln("b2.val: %d", b2.val);
> 	
> 	const B b3 = cast(B) a;
> 	
> 	B b4 = const_cast(b3);
> }
> [/code]
>
> print:
>
> alias_this_impl.d(24): Error: function alias_this_impl.A.opCast!(B).opCast () is
>  not callable using argument types ()
> alias_this_impl.d(44): Error: template instance alias_this_impl.const_cast!(B) e
> rror instantiating
>
> I'm not very skillful in such "template" stories. Maybe someone can help me?

Solved with

T const_cast(T)(const T obj) {
	return to!(T)(obj);
}

But i think that there must exist a more nicer way to cast away const, isn't there?

To cast away "const" with a simple cast to "T" fails (see my post above), because i have no idea, how i can restrict my opCast. So i have to convert it again with "to". Do some of you have any ideas how i can restrict my opCast, so my const_cast doesn't match it, e.g. with some template magic?
May 03, 2012
On Thu, 03 May 2012 00:38:35 +0200, Namespace <rswhite4@googlemail.com> wrote:

> I'm not very skillful in such "template" stories. Maybe someone can help me?

The main problem here is your opCast is non-const. (it's always an indication of
const problems when DMD says "<X> is not callable using argument types ()")

Solution:

class A {
    int val;

    alias val this;

    T opCast(T : Object)() {
        writeln("FOO");

        return to!(T)(this);
    }

    // Add this
    T opCast(T : Object)() const {
        writeln("FOO");

        return to!(T)(this);
    }
}
May 03, 2012
On Thursday, May 03, 2012 09:33:01 Namespace wrote:
> On Wednesday, 2 May 2012 at 22:38:36 UTC, Namespace wrote:
> > Other, shorter example:
> > 
> > [code]
> > import std.stdio, std.traits;
> > 
> > class A {
> > 
> > 	int val;
> > 
> > 	alias val this;
> > 
> > 	T opCast(T : Object)() {
> > 
> > 		writeln("FOO");
> > 
> > 		return to!(T)(this);
> > 
> > 	}
> > 
> > }
> > 
> > class B : A {
> > 
> > }
> > 
> > T to(T : Object, U : Object)(const U obj) {
> > 
> > 	return *(cast(T*) &obj);
> > 
> > }
> > 
> > T const_cast(T)(const T obj) {
> > 
> > 	return cast(T) obj;
> > 
> > }
> > 
> > void main () {
> > 
> > 	A a = new B();
> > 	a.val = 42;
> > 
> > 	writefln("a.val: %d", a.val);
> > 
> > 	B* b = cast(B*) &a;
> > 	writefln("*b.val: %d", b.val);
> > 
> > 	B b1 = to!(B)(a);
> > 	writefln("b1.val: %d", b1.val);
> > 
> > 	B b2 = cast(B) a;
> > 	writefln("b2.val: %d", b2.val);
> > 
> > 	const B b3 = cast(B) a;
> > 
> > 	B b4 = const_cast(b3);
> > 
> > }
> > [/code]
> > 
> > print:
> > 
> > alias_this_impl.d(24): Error: function
> > alias_this_impl.A.opCast!(B).opCast () is
> > 
> >  not callable using argument types ()
> > 
> > alias_this_impl.d(44): Error: template instance
> > alias_this_impl.const_cast!(B) e
> > rror instantiating
> > 
> > I'm not very skillful in such "template" stories. Maybe someone can help me?
> 
> Solved with
> 
> T const_cast(T)(const T obj) {
> 	return to!(T)(obj);
> }
> 
> But i think that there must exist a more nicer way to cast away const, isn't there?
> 
> To cast away "const" with a simple cast to "T" fails (see my post above), because i have no idea, how i can restrict my opCast. So i have to convert it again with "to". Do some of you have any ideas how i can restrict my opCast, so my const_cast doesn't match it, e.g. with some template magic?

If you want to restrict opCast, then use a template constraint, constraining it to what you want to work with it. Also, casting away const is generally a bad idea in D. Casting away const and mutating a variable is an _extremely_ bad idea. You _really_ shouldn't be doing it. So, the fact that you _have_ a function which is specifically trying to cast away const is almost certainly _not_ a good idea.

http://stackoverflow.com/questions/4219600/logical-const-in-d


- Jonathan M Davis
« First   ‹ Prev
1 2