Thread overview
Automatic return type covariance for functions that return this?
Sep 15, 2012
Ben Davis
Sep 15, 2012
Ben Davis
Sep 15, 2012
Andrej Mitrovic
Sep 15, 2012
Andrej Mitrovic
Sep 15, 2012
bearophile
Sep 15, 2012
Andrej Mitrovic
September 15, 2012
Hi,

Is it possible in D to achieve this effect:

class Super {
  typeof(this) doStuff() { ...; return this; }
}

class Sub : Super {
  //doStuff is NOT explicitly overridden here
}

Sub x = (new Sub()).doStuff();

The last line doesn't compile because doStuff() returns Super. Is there a way to make it return Sub without having to explicitly override the function?

Thanks in advance,

Ben :)
September 15, 2012
Never mind, I found the answer in the 'templates' page of the spec:

class Super {
   T doStuff(this T)() { ...; return cast(T)this; }
}

Sub x = (new Sub()).doStuff();

It seems a bit of a shame that I need the cast, but it's a small thing :)

On 15/09/2012 22:53, Ben Davis wrote:
> Hi,
>
> Is it possible in D to achieve this effect:
>
> class Super {
>    typeof(this) doStuff() { ...; return this; }
> }
>
> class Sub : Super {
>    //doStuff is NOT explicitly overridden here
> }
>
> Sub x = (new Sub()).doStuff();
>
> The last line doesn't compile because doStuff() returns Super. Is there
> a way to make it return Sub without having to explicitly override the
> function?
>
> Thanks in advance,
>
> Ben :)

September 15, 2012
On 9/15/12, Ben Davis <entheh@cantab.net> wrote:
> The last line doesn't compile because doStuff() returns Super. Is there a way to make it return Sub without having to explicitly override the function?

You need a dynamic cast at the call site:

Sub x = cast(Sub)(new Sub()).doStuff();

x will be null if doStuff doesn't actually return a Sub object (replace 'new Sub' with 'new Super' for demonstration).

You can't guarantee that the 'this' reference returned in the base class doStuff method will be of dynamic type 'Sub', that's why implicit conversions don't work. Either define this method in every subclass or use casts at the call site.

Maybe you're looking for automatic injection of code into every subclass, but I don't think this is possible in D. Using mixins might work, but you'd still have to instantiate a mixin in every subclass by hand.
September 15, 2012
On 9/15/12, Ben Davis <entheh@cantab.net> wrote:
> Never mind, I found the answer in the 'templates' page of the spec:
>
> class Super {
>     T doStuff(this T)() { ...; return cast(T)this; }
> }
>
> Sub x = (new Sub()).doStuff();
>
> It seems a bit of a shame that I need the cast, but it's a small thing :)

Ah the template this solution, I always forget about that little trick! Nicely done. :)
September 15, 2012
On 9/15/12, Ben Davis <entheh@cantab.net> wrote:
> Never mind, I found the answer in the 'templates' page of the spec:
>
> class Super {
>     T doStuff(this T)() { ...; return cast(T)this; }
> }

Btw I think that's a dynamic cast, unless the compiler can optimize it (I mean it should since it's a template function right?). I saw this static cast thingy laying around somewhere:

auto static_cast(T,U)(U source)
{
    return cast(T)(cast(void*)source);
}
September 15, 2012
Andrej Mitrovic:

> I saw this
> static cast thingy laying around somewhere:
>
> auto static_cast(T,U)(U source)
> {
>     return cast(T)(cast(void*)source);
> }

Maybe you meant:
http://d.puremagic.com/issues/show_bug.cgi?id=5559

Bye,
bearophile