digitalmars.D - Defining a single opCast disables explicit cast to base interfaces
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (41/41) Mar 16 2015 The following program compiles fine:
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (4/4) Mar 16 2015 I forgot to mention that this discussion is carried over from the
- jkpl (15/57) Mar 17 2015 There is also another trick: generally when something cannot be
- Jonathan M Davis via Digitalmars-d (13/52) Mar 18 2015 Defining opCast destroys basically all built-in casts, which I think is ...
The following program compiles fine: interface I {} class B : I {} class C : B { int i; } void main() { auto c = new C; auto i = cast(I)c; // compiles auto b = cast(B)c; // compiles } Let's add an unrelated opCast to C: class C : B { int i; int opCast(T : int)() { return i; } } Now the last two lines of main fail to compile: Error: template instance opCast!(I) does not match template declaration opCast(T : int)() Error: template instance opCast!(B) does not match template declaration opCast(T : int)() Is this per spec? (Actually, where is the spec? (Trick question. ;) ) There is a workaround: Add a catch-all opCast that forwards to the all-powerful std.conv.to: T opCast(T)() { import std.conv; return this.to!T; } Now it compiles and works as expected. However, the question remains... Thank you, Ali
Mar 16 2015
I forgot to mention that this discussion is carried over from the D.learn newsgroup: http://forum.dlang.org/thread/uwuvqurfqbetypdlwkdy forum.dlang.org Ali
Mar 16 2015
On Tuesday, 17 March 2015 at 05:27:38 UTC, Ali Çehreli wrote:The following program compiles fine: interface I {} class B : I {} class C : B { int i; } void main() { auto c = new C; auto i = cast(I)c; // compiles auto b = cast(B)c; // compiles } Let's add an unrelated opCast to C: class C : B { int i; int opCast(T : int)() { return i; } } Now the last two lines of main fail to compile: Error: template instance opCast!(I) does not match template declaration opCast(T : int)() Error: template instance opCast!(B) does not match template declaration opCast(T : int)() Is this per spec? (Actually, where is the spec? (Trick question. ;) ) There is a workaround: Add a catch-all opCast that forwards to the all-powerful std.conv.to: T opCast(T)() { import std.conv; return this.to!T; } Now it compiles and works as expected. However, the question remains... Thank you, AliThere is also another trick: generally when something cannot be cast then it's often possible to cast it as a pointer to the cast type that is directly derefered. And it work... --- T opCast(T)() { static if(is(T==int)) return i; else return *cast(T*) &this; } --- ...ed until version 2.067 (now it's deprecated because of &this since this is already a ptr).
Mar 17 2015
On Monday, March 16, 2015 22:27:36 Ali Çehreli via Digitalmars-d wrote:The following program compiles fine: interface I {} class B : I {} class C : B { int i; } void main() { auto c = new C; auto i = cast(I)c; // compiles auto b = cast(B)c; // compiles } Let's add an unrelated opCast to C: class C : B { int i; int opCast(T : int)() { return i; } } Now the last two lines of main fail to compile: Error: template instance opCast!(I) does not match template declaration opCast(T : int)() Error: template instance opCast!(B) does not match template declaration opCast(T : int)() Is this per spec? (Actually, where is the spec? (Trick question. ;) ) There is a workaround: Add a catch-all opCast that forwards to the all-powerful std.conv.to: T opCast(T)() { import std.conv; return this.to!T; } Now it compiles and works as expected. However, the question remains...Defining opCast destroys basically all built-in casts, which I think is a horrible idea. The problem that you're describing was reported a couple of years ago: https://issues.dlang.org/show_bug.cgi?id=9249 But it also affects stuff like shared, and a bug report for that was created four years ago: https://issues.dlang.org/show_bug.cgi?id=5747 And there may be other bug reports for similar issues, but basically, as it stands, declaring opCast borks the built-in casts, forcing you to redefine them all, which is horrible IMHO. But Kenji expressed concern about fixing - Jonathan M Davis
Mar 18 2015