Defining a single opCast disables explicit cast to base interfaces
Jonathan M Davis via Digitalmars-d
digitalmars-d at puremagic.com
Wed Mar 18 03:25:29 PDT 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
it in #5747, and no one has stepped up to sort it out.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list