Thread overview
I need an Easy example to understand Alias This
Jul 07, 2020
Marcone
Jul 07, 2020
Ali Çehreli
Jul 07, 2020
Marcone
Jul 07, 2020
Ali Çehreli
Jul 07, 2020
Cym13
Jul 07, 2020
Ferhat Kurtulmuş
July 07, 2020
Hi, I study Dlang for one year, and I can't understand alias this. I need an Easy example to understand Alias This.
July 06, 2020
On 7/6/20 5:35 PM, Marcone wrote:
> Hi, I study Dlang for one year, and I can't understand alias this. I need an Easy example to understand Alias This.

Is the following example useful?

  http://ddili.org/ders/d.en/alias_this.html

Ali
July 07, 2020
On Tuesday, 7 July 2020 at 00:42:40 UTC, Ali Çehreli wrote:
> On 7/6/20 5:35 PM, Marcone wrote:
>> Hi, I study Dlang for one year, and I can't understand alias this. I need an Easy example to understand Alias This.
>
> Is the following example useful?
>
>   http://ddili.org/ders/d.en/alias_this.html
>
> Ali

I can't undestand it. I need a simple example.
July 06, 2020
On 7/6/20 5:44 PM, Marcone wrote:
> On Tuesday, 7 July 2020 at 00:42:40 UTC, Ali Çehreli wrote:
>> On 7/6/20 5:35 PM, Marcone wrote:
>>> Hi, I study Dlang for one year, and I can't understand alias this. I need an Easy example to understand Alias This.
>>
>> Is the following example useful?
>>
>>   http://ddili.org/ders/d.en/alias_this.html
>>
>> Ali
> 
> I can't undestand it. I need a simple example.

I find the example of converting two integers to double to be a simple example of 'alias this'. (If it's not simple, then there is another example later.)

So, allow me to change the name of the struct. :) Let's say we have a Money class that stores dollars and cents as two separate members. This class also has a member function that returns the amount as double:

struct Money {
  long dollars;
  long cents;

  double value() const {
    return double(cents) / 100 + dollars;
  }
}

unittest {
  assert(Money(10, 50).value == 10.5);
}

void main() {
}

So far so good: We can get the value by calling value().

*If* this is a type where conversion to double should be automatic, then calling value() all over the place might be considered cumbersome and too wordy. If that's true, we may want to get the value of this type automatically as double. For example, we may want to be able to call the following function with Money:

void foo(double d) {
  // ...
}

void main() {
  foo(Money(20, 50));  // <-- Compilation error
}

Currently the code fails to compile because Money is not 'double'. (Note: Arguably, Money is not a type that should be converted to double automatically, but again, I find this example simple.)

'alias this' allows a type to be converted to a specific type automatically. For example, if we want to convert Money objects automatically to 'double', then we use the following line inside the struct defition:

  alias value this;

What that line means is this: "Dear compiler, please automatically convert this type to whatever the type of the 'value' member is." In this case, "Allow using an object of Money wherever that object is used in place of a double."

So, with that addition, now the call inside main compiles and foo() gets called with 'Money(20, 50).value' (compiler injects an automatic call to value()).

Here is the complete program:

struct Money {
  long dollars;
  long cents;

  double value() const {
    return double(cents) / 100 + dollars;
  }

  alias value this;  // <-- ADDED
}

unittest {
  assert(Money(10, 50).value == 10.5);
}

void foo(double d) {
  // ...
}

void main() {
  foo(Money(20, 50));
}

'alias this' is sometimes used where a type needs to behave like some other type with some added functionality. For example, here is another example where a Month type should behave like an 'int' but it cannot have any value other than 1-12:

struct Month {
  int value;

  this(int value) {
    this.value = value;
  }

  invariant() {
    assert(value >= 1);
    assert(value <= 12);
  }

  alias value this;
}

unittest {
  import std.exception;

  assertThrown!Error(Month(0));
  assertThrown!Error(Month(13));

  void foo(int) {
  }

  // 'alias this' allows the following call to foo()
  assert(__traits(compiles, foo(Month(3))));
}

void main() {
}

Ali

July 07, 2020
On Tuesday, 7 July 2020 at 00:44:32 UTC, Marcone wrote:
> On Tuesday, 7 July 2020 at 00:42:40 UTC, Ali Çehreli wrote:
>> On 7/6/20 5:35 PM, Marcone wrote:
>>> Hi, I study Dlang for one year, and I can't understand alias this. I need an Easy example to understand Alias This.
>>
>> Is the following example useful?
>>
>>   http://ddili.org/ders/d.en/alias_this.html
>>
>> Ali
>
> I can't undestand it. I need a simple example.

This only scrapes the surface, but it should give an idea of the core mechanics and why it's regarded as an important concept.


import std.stdio;

struct Fruit {
    string name;
}

struct ColoredFruit {
    Fruit _fruit;
    alias _fruit this;

    string color;
}

void printColoredFruit(ColoredFruit f) {
    writeln(f.color, " ", f.name);
}

void printGeneralFruit(Fruit f) {
    writeln(f.name);
}

void main(string[] args) {
    ColoredFruit banana;
    banana.color = "yellow"; // It's a normal struct for its non-alias members
    banana.name  = "banana"; // We can interact with internal fields directly

    // This function accepts a ColoredFruit so the whole banana is passed.
    printColoredFruit(banana);
    // > yellow banana

    // This function only doesn't accept a ColoredFruit, but it does accept a
    // Fruit and we have a Fruit alias this so the internal _fruit is passed.
    printGeneralFruit(banana);
    // > banana
}

July 07, 2020
On Tuesday, 7 July 2020 at 00:35:38 UTC, Marcone wrote:
> Hi, I study Dlang for one year, and I can't understand alias this. I need an Easy example to understand Alias This.

I used it for widget inheritance in my experimental code here,

https://github.com/aferust/noobgui/blob/master/source/widget.d