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 | |
|---|---|
Posted in reply to Namespace | 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 | |
|---|---|
Posted in reply to Namespace | 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 | |
|---|---|
Posted in reply to Namespace | 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 | |
|---|---|
Posted in reply to Jesse Phillips | 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 | |
|---|---|
Posted in reply to Namespace | 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 | |
|---|---|
Posted in reply to Namespace | 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 | |
|---|---|
Posted in reply to Namespace | 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 | |
|---|---|
Posted in reply to Namespace | 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 | |
|---|---|
Posted in reply to Namespace | 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 |
|---|

Reply