Thread overview
static alias this and if/do/while/for
Oct 22, 2020
Jack Applegame
Oct 26, 2020
Vladimirs Nordholm
Oct 26, 2020
Q. Schroll
October 22, 2020
There is a funny feature (or bug) in the D language:

static alias this and static operator overloading.

For example

> interface Foo {
>     static {
>         int value;
>         void opAssign(int v) { value = v; }
>         int get() { return value; }
>         alias get this;
>     }
> }

Now we can use type Foo as if it were an lvalue/rvalue:

> Foo = 5;
> int a = Foo;
> int b = Foo + a;

I heavily use this feature in my MCU library.

But it doesn't work inside conditionals:

> if(Foo) {}    // Error: type Foo is not an expression
> while(Foo) {} // Error: type Foo is not an expression

Even if we define `static opCast!bool()`. It doesn't help.

Should this be fixed?

October 26, 2020
On Thursday, 22 October 2020 at 21:55:59 UTC, Jack Applegame wrote:
> Now we can use type Foo as if it were an lvalue/rvalue:
>
>> Foo = 5;
>> int a = Foo;
>> int b = Foo + a;

Haha, that's pretty neat!
October 26, 2020
On Thursday, 22 October 2020 at 21:55:59 UTC, Jack Applegame wrote:
> There is a funny feature (or bug) in the D language:
>
> static alias this and static operator overloading.
>
> For example
>
>> interface Foo {
>>     static {
>>         int value;
>>         void opAssign(int v) { value = v; }
>>         int get() { return value; }
>>         alias get this;
>>     }
>> }
>
> Now we can use type Foo as if it were an lvalue/rvalue:
>
>> Foo = 5;
>> int a = Foo;
>> int b = Foo + a;
>
> I heavily use this feature in my MCU library.

It doesn't surprise me that much. What actually did was that static opIndex() works. Consider this:

    struct X
    {
        static int opIndex() { return 1; }
    }

    alias SliceOf(T) = T[];
    enum ValueOf(T) = T[];

    static assert( ! is(int[SliceOf!X] == int[ValueOf!X]));

But static opIndex and friends can be useful: https://run.dlang.io/is/s15zS0 I'd actually find it awesome if we had opCallAssign and opCallOpAssign; the reason I used opIndex and not opCall is that way, one gets access to the right-hand side and to-assign parameters by reference, so no internal pointer stuff's needed.

> But it doesn't work inside conditionals:
>
>> if(Foo) {}    // Error: type Foo is not an expression
>> while(Foo) {} // Error: type Foo is not an expression
>
> Even if we define `static opCast!bool()`. It doesn't help.

Only using Foo.opCast!bool works; cast(bool) won't compile.

> Should this be fixed?

The bool stuff should be fixed. The other direction would be a breaking change.