Thread overview
Inherit from class based on bool value
Nov 13, 2018
Jamie
Nov 13, 2018
Ali Çehreli
Nov 13, 2018
Jamie
Nov 13, 2018
Stanislav Blinov
Nov 13, 2018
Basile B.
Nov 15, 2018
Bienlein
Nov 15, 2018
bauss
November 13, 2018
I would like my class to inherit from one of two classes based on a boolean value known at compile time. Something like this:

void main()
{
    Top!(OPTION.FALSE) top = new Top!(OPTION.FALSE);
}

enum OPTION
{
    FALSE = 0.,
    TRUE = 1.
}

class One
{}

class Two
{}

class Top(OPTION option) : option ? One : Two
{}

Is this possible? I can't get it to work in the way I'm showing above.
Cheers
November 12, 2018
On 11/12/2018 11:10 PM, Jamie wrote:
> I would like my class to inherit from one of two classes based on a
> boolean value known at compile time. Something like this:
>
> void main()
> {
>      Top!(OPTION.FALSE) top = new Top!(OPTION.FALSE);
> }
>
> enum OPTION
> {
>      FALSE = 0.,
>      TRUE = 1.
> }
>
> class One
> {}
>
> class Two
> {}
>
> class Top(OPTION option) : option ? One : Two
> {}
>
> Is this possible? I can't get it to work in the way I'm showing above.
> Cheers

I got it working inside an eponymous template. D is pretty cool actually. :)

enum OPTION
{
    FALSE = 0.,
    TRUE = 1.
}

class One
{}

class Two
{}

template Top(OPTION option) {
    static if (option == OPTION.TRUE) {
        alias Base = One;

    } else {
        alias Base = Two;
    }

    class Top : Base
    {}
}

void main() {
    auto a = new Top!(OPTION.FALSE);
    auto b = new Top!(OPTION.TRUE);
}

Ali

November 13, 2018
On Tuesday, 13 November 2018 at 07:10:26 UTC, Jamie wrote:

> Is this possible? I can't get it to work in the way I'm showing above.

...or abstract away Ali's solution:

enum OPTION {
    FALSE,
    TRUE,
}

template Select(OPTION opt, IfTrue, IfFalse) {
    static if (opt == OPTION.TRUE) alias Select = IfTrue;
    else alias Select = IfFalse;
}

class One {}
class Two {}

class Top(OPTION opt) : Select!(opt, One, Two) {}

void main() {
    import std.traits : BaseClassesTuple;
    auto t1 = new Top!(OPTION.TRUE);
    static assert(is(BaseClassesTuple!(typeof(t1))[0] == One));
    auto t2 = new Top!(OPTION.FALSE);
    static assert(is(BaseClassesTuple!(typeof(t2))[0] == Two));
}

November 13, 2018
On Tuesday, 13 November 2018 at 07:29:30 UTC, Ali Çehreli wrote:
> On 11/12/2018 11:10 PM, Jamie wrote:
> > I would like my class to inherit from one of two classes ...
> > Is this possible? I can't get it to work in the way I'm
> showing above.
> > Cheers
>
> I got it working inside an eponymous template. D is pretty cool actually. :)
>
> enum OPTION
> {
>     FALSE = 0.,
>     TRUE = 1.
> }
>
> class One
> {}
>
> class Two
> {}
>
> template Top(OPTION option) {
>     static if (option == OPTION.TRUE) {
>         alias Base = One;
>
>     } else {
>         alias Base = Two;
>     }
>
>     class Top : Base
>     {}
> }
>
> void main() {
>     auto a = new Top!(OPTION.FALSE);
>     auto b = new Top!(OPTION.TRUE);
> }
>
> Ali

Wow that's nifty, thanks very much! And thanks for the speedy response
November 13, 2018
On Tuesday, 13 November 2018 at 07:10:26 UTC, Jamie wrote:
> I would like my class to inherit from one of two classes based on a boolean value known at compile time. Something like this:
>
> void main()
> {
>     Top!(OPTION.FALSE) top = new Top!(OPTION.FALSE);
> }
>
> enum OPTION
> {
>     FALSE = 0.,
>     TRUE = 1.
> }
>
> class One
> {}
>
> class Two
> {}
>
> class Top(OPTION option) : option ? One : Two
> {}
>
> Is this possible? I can't get it to work in the way I'm showing above.
> Cheers

You can use an alias seq :

void main()
{
    Top!(OPTION.FALSE) top = new Top!(OPTION.FALSE);
}

enum OPTION
{
    FALSE = 0,
    TRUE = 1
}

class One
{}

class Two
{}

import std.meta : AliasSeq;
alias Bases = AliasSeq!(One, Two);

class Top(OPTION option) : Bases[option]
{}
November 15, 2018
On Tuesday, 13 November 2018 at 07:10:26 UTC, Jamie wrote:
> I would like my class to inherit from one of two classes based on a boolean value known at compile time. Something like this:
>
> void main()
> {
>     Top!(OPTION.FALSE) top = new Top!(OPTION.FALSE);
> }
>
> enum OPTION
> {
>     FALSE = 0.,
>     TRUE = 1.
> }
>
> class One
> {}
>
> class Two
> {}
>
> class Top(OPTION option) : option ? One : Two
> {}
>
> Is this possible? I can't get it to work in the way I'm showing above.
> Cheers

My piece of advice would be not to do this but to model all data explicitly. And I had some exposure to OOP with over 10 years developing in Smalltalk, which is a pure OO language. Actually, I don't know whether it is good that this can be done in D ...
November 15, 2018
On Thursday, 15 November 2018 at 08:46:36 UTC, Bienlein wrote:
> On Tuesday, 13 November 2018 at 07:10:26 UTC, Jamie wrote:
>> I would like my class to inherit from one of two classes based on a boolean value known at compile time. Something like this:
>>
>> void main()
>> {
>>     Top!(OPTION.FALSE) top = new Top!(OPTION.FALSE);
>> }
>>
>> enum OPTION
>> {
>>     FALSE = 0.,
>>     TRUE = 1.
>> }
>>
>> class One
>> {}
>>
>> class Two
>> {}
>>
>> class Top(OPTION option) : option ? One : Two
>> {}
>>
>> Is this possible? I can't get it to work in the way I'm showing above.
>> Cheers
>
> My piece of advice would be not to do this but to model all data explicitly. And I had some exposure to OOP with over 10 years developing in Smalltalk, which is a pure OO language. Actually, I don't know whether it is good that this can be done in D ...

It's really no different than doing it manually and it's prettier than if it was done using a mixin, in which you'd not be able to limit it at all.

D is not an OOP language and it doesn't even conform to standard OOP practices so really it doesn't matter.

What doesn't make sense in one language, might make sense in another language.

I feel like restrictions often limit the full potential of a language, more often than it damages it.

Depending on the use-case this might make sense. It would actually be very useful for exceptions/errors in D.

Something like:

template ExceptionParent(Parent = Exception)
{
   static if (flagsThatDeterminesItsDebugMode)
   {
       alias ExceptionParent = Error;
   }
   else
   {
       alias ExceptionParent = Parent;
   }
}

class MyException : ExceptionParent!()
{
    ...
}

Now when debugging all exceptions will be error and when it's not debugging it'll be an exception.