www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using multiple mixin templates to implement operator overloading

reply Tobias Pankrath <tobias+dlang pankrath.net> writes:
I want to wrap e.g. an int and implement basic arithmetic. In the 
provided example [1] I use  two mixin templates to separately 
implement scaling (multiplication with int/double) and addition 
and subtraction with the type itself.

In the end I want to have several distinct wrappers and allow 
specific operations between them and int / double. It's important 
that the return values are typed correctly, otherwise I could use 
std.typecons.Proxy.

My problem is that both overloads of opBinary work, but not at 
the same time. As soon as I mixin both templates, they stop to 
work. If I just paste the implementation into the body of 
WrapInt, they work both at the same time though.

Could someone explain the mechanics behind it?

Thanks!

[1] https://run.dlang.io/is/WbG987
Dec 12 2020
parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 12 December 2020 at 17:36:57 UTC, Tobias Pankrath 
wrote:
 I want to wrap e.g. an int and implement basic arithmetic. In 
 the provided example [1] I use  two mixin templates to 
 separately implement scaling (multiplication with int/double) 
 and addition and subtraction with the type itself.

 In the end I want to have several distinct wrappers and allow 
 specific operations between them and int / double. It's 
 important that the return values are typed correctly, otherwise 
 I could use std.typecons.Proxy.

 My problem is that both overloads of opBinary work, but not at 
 the same time. As soon as I mixin both templates, they stop to 
 work. If I just paste the implementation into the body of 
 WrapInt, they work both at the same time though.

 Could someone explain the mechanics behind it?

 Thanks!

 [1] https://run.dlang.io/is/WbG987
Functions from different mixin templates can't overload each other. The reason for this is that, when you mix in a mixin template, it does not *actually* add the declarations inside it to a current scope: instead, it adds them to a new scope, and then (essentially) "imports" them into the current scope. IMO this is one of the stupider design decisions in D, but it's unlikely it will ever be fixed. The easiest workaround is to use string mixins instead, which work the way you'd expect them to.
Dec 12 2020
next sibling parent Tobias Pankrath <tobias+dlang pankrath.net> writes:
On Saturday, 12 December 2020 at 18:14:31 UTC, Paul Backus wrote:
 Functions from different mixin templates can't overload each 
 other. The reason for this is that, when you mix in a mixin 
 template, it does not *actually* add the declarations inside it 
 to a current scope: instead, it adds them to a new scope, and 
 then (essentially) "imports" them into the current scope.
Much appreciated! Exactly the explanation I needed.
Dec 12 2020
prev sibling next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 12 December 2020 at 18:14:31 UTC, Paul Backus wrote:
 IMO this is one of the stupider design decisions in D, but it's 
 unlikely it will ever be fixed.
It is useful in several other contexts though, including user overriding and private data stores for the mixin.
 The easiest workaround is to use string mixins instead, which 
 work the way you'd expect them to.
But yeah. The other alternative is to alias them together: class A { mixin Whatever a; // need to give it a name here to reference later mixin Whatever b; // explicitly merge overloads here alias opBinary = a.opBinary; alias opBinary = b.opBinary; } Or you can do a forwarder function yourself but that's getting even more a hassle. Sometimes appropriate though.
Dec 12 2020
parent Paul Backus <snarwin gmail.com> writes:
On Saturday, 12 December 2020 at 20:25:48 UTC, Adam D. Ruppe 
wrote:
 On Saturday, 12 December 2020 at 18:14:31 UTC, Paul Backus 
 wrote:
 IMO this is one of the stupider design decisions in D, but 
 it's unlikely it will ever be fixed.
It is useful in several other contexts though, including user overriding and private data stores for the mixin.
Sure, but you can always opt in to that behavior by giving the mixin a name. The fact that you can't opt out of it even if you want to is the issue. It's essentially the same flaw Andrei criticized C++'s `if constexpr` for [1]. [1] https://www.youtube.com/watch?v=tcyb1lpEHm0&t=45m20s
Dec 12 2020
prev sibling parent reply Dennis <dkorpel gmail.com> writes:
On Saturday, 12 December 2020 at 18:14:31 UTC, Paul Backus wrote:
 IMO this is one of the stupider design decisions in D, but it's 
 unlikely it will ever be fixed. The easiest workaround is to 
 use string mixins instead, which work the way you'd expect them 
 to.
If issue 19365 got fixed, it could be done with an alias instead. https://issues.dlang.org/show_bug.cgi?id=19365 Currently string mixins are indeed the best option though.
Dec 12 2020
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 12 December 2020 at 20:26:00 UTC, Dennis wrote:
 If issue 19365 got fixed
eeek I thought that was fixed but apparently not :( so yeah alias won't work for operator overloads. Does work for other functions so good technique to know but not here. So for op prolly go with the string mixin....
Dec 12 2020