View mode: basic / threaded / horizontal-split · Log in · Help
April 28, 2012
cannot cast
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
Re: cannot cast
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
alias this : cast turns into endless loop
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
Re: cannot cast
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
Re: cannot cast
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
Re: cannot cast
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
Re: cannot cast
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
Re: cannot cast
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
Re: cannot cast
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
Re: cannot cast
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
Top | Discussion index | About this forum | D home