www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to alias

reply kyle <kyle kyle.kyle> writes:
I'm trying to use ```alias``` in an operator overload to reduce 
typing, but what gets aliased is not what I expect. Tested in DMD 
v2.098.1-dirty on Windows plus whatever versions of DMD, GDC, and 
LDC I have installed on Linux. Thanks.

```
struct Broke
{
     double num;

     import std.traits : isNumeric;
     Broke opBinary(string op, T)(T rhs) if (is(T : Broke) || 
isNumeric!T)
     {
         static if ( is(T : Broke))
         {
             alias b = rhs.num;
             assert(&b != &this.num); //this fails
         }
         else
         {
             alias b = rhs;
         }

         static if (op == "+")
         {
             return Broke(num + b);
         }
     }
}

void main()
{
     import std.stdio;

     Broke foo = Broke(10);
     Broke bar = Broke(20);

     writeln(foo + 15);  //prints 25 as expected
     writeln(foo + bar); //prints 20
}
```
Jan 14 2022
next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Friday, 14 January 2022 at 17:48:41 UTC, kyle wrote:
 I'm trying to use ```alias``` in an operator overload to reduce 
 typing, but what gets aliased is not what I expect.
alias works in term of compile-time names, not values. This means the `this` value, being run time, gets discarded. alias b = rhs.num; drops the this, instead doing something more like `alias b = Broke.num;`. It'd work if it was static, or if you re-attach the this later, which is what actually happens in that assert, but not otherwise. This commonly surprises people but the behavior is sometimes useful, i just wish it didn't look the same as something so different. Easiest thing to do instead is to just use a ref helper function: ref b() { return rhs.num; } assert(&b() != &this.num); //this works now (With the -preview=shortenedMethods you can write it `ref b() => rhs.num;` too nut in both cases, you must call the function as b() when you use it) Or, of course here, the num is just a value so you can simply use an intermediate variable too.
Jan 14 2022
parent reply kyle <kyle kyle.kyle> writes:
On Friday, 14 January 2022 at 17:56:48 UTC, Adam D Ruppe wrote:
 On Friday, 14 January 2022 at 17:48:41 UTC, kyle wrote:
 [...]
alias works in term of compile-time names, not values. This means the `this` value, being run time, gets discarded. [...]
Thanks Adam. We need a repository of articles about stuff that doesn't do what people expect.
Jan 14 2022
parent Adam D Ruppe <destructionator gmail.com> writes:
On Friday, 14 January 2022 at 18:04:35 UTC, kyle wrote:
 Thanks Adam. We need a repository of articles about stuff that 
 doesn't do what people expect.
I put this as a tip of the week in my late post: http://dpldocs.info/this-week-in-d/Blog.Posted_2022_01_10.html#tip-of-the-week My blog sometimes gets these if you do a ctrl+f search on the index sometimes something will come up.
Jan 18 2022
prev sibling parent Salih Dincer <salihdb hotmail.com> writes:
On Friday, 14 January 2022 at 17:48:41 UTC, kyle wrote:
```d
 void main()
 {
     import std.stdio;

     Broke foo = Broke(10);
     Broke bar = Broke(20);

     writeln(foo + 15);  //prints 25 as expected
     writeln(foo + bar); //prints 20
 }
 ```
I guess what you want to do is something like this: ```d struct Broke { double num; Broke opBinary(string op)(Broke rhs) if(op == "+") { return Broke(this.num + rhs.num);/* this.num += rhs.num; return this;//*option 2*/ } Broke opBinary(string op)(double rhs) if(op == "+") { return Broke(this.num + rhs);/* this.num += rhs; return this;//*option 2*/ } } void main() { import std.stdio; Broke foo = Broke(5); Broke bar = Broke(15); } ``` So you don't need to use alias. If you want it the other way (option 2), turn off option 1 then option 2 will open automatically. Thus, same Broke() gets values: 20, 35 and 55. regards, - Salih
Jan 20 2022