www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - opBinary : Static ifs or specialization?

reply claptrap <clap trap.com> writes:
So you have opBinary and half a dozen operators to implement. Do 
you use a separate method for each operator or do you have one 
method and a big static if else if to select code path?

I assume they are functionally equivalent? So its just about 
style?
Jun 23 2020
next sibling parent Meta <jared771 gmail.com> writes:
On Tuesday, 23 June 2020 at 23:53:36 UTC, claptrap wrote:
 So you have opBinary and half a dozen operators to implement. 
 Do you use a separate method for each operator or do you have 
 one method and a big static if else if to select code path?

 I assume they are functionally equivalent? So its just about 
 style?
An idiomatic example: import std.algorithm: among; struct Test { int payload; Test opBinary(string op)(Test other) if (op.among!("+", "-", "*", "/")) //Limit supported ops { mixin("return Test(payload " ~ op ~ "other.val);"); } int opBinary(string op)(int n) //No constraint; support the full range of integer operations { mixin("return payload " ~ op ~ "n;"); } }
Jun 23 2020
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Jun 23, 2020 at 11:53:36PM +0000, claptrap via Digitalmars-d-learn
wrote:
 So you have opBinary and half a dozen operators to implement. Do you
 use a separate method for each operator or do you have one method and
 a big static if else if to select code path?
[...] If your implementations are based on built-in operators, you could use mixins to unify the implementations into one, e.g.: struct MyInt { int i; MyInt opBinary(string op)(MyInt arg) { return MyInt(mixin("i "~op~" arg.i")); } } which has far less boilerplate than separately implementing each operator. This is one of the main reasons for the design of .opBinary. T -- Let's eat some disquits while we format the biskettes.
Jun 23 2020
parent reply claptrap <clap trap.com> writes:
On Wednesday, 24 June 2020 at 00:53:58 UTC, H. S. Teoh wrote:
 On Tue, Jun 23, 2020 at 11:53:36PM +0000, claptrap via

 If your implementations are based on built-in operators, you 
 could use mixins to unify the implementations into one, e.g.:
Ah yeah thats useful, to expand a bit what about if the RHS is a different type? Point!T opBinary(string op, RHS)(RHS rhs) { static if (is(RHS == Point!float) || is(RHS == Point!double)) { // .. etc.. } else static if (is(RHS == float) || is(RHS == double)) { // etc... } else static if (is(RHS == float[2]) || is(RHS == double[2])) { // .. etc... } assert(0); // type not supported } should that be split up?
Jun 24 2020
parent Dominikus Dittes Scherkl <dominikus.scherkl continental-corporation.com> writes:
On Wednesday, 24 June 2020 at 09:01:28 UTC, claptrap wrote:
 On Wednesday, 24 June 2020 at 00:53:58 UTC, H. S. Teoh wrote:
 On Tue, Jun 23, 2020 at 11:53:36PM +0000, claptrap via

 If your implementations are based on built-in operators, you 
 could use mixins to unify the implementations into one, e.g.:
Ah yeah thats useful, to expand a bit what about if the RHS is a different type? Point!T opBinary(string op, RHS)(RHS rhs) { static if (is(RHS == Point!float) || is(RHS == Point!double)) { // .. etc.. } else static if (is(RHS == float) || is(RHS == double)) { // etc... } else static if (is(RHS == float[2]) || is(RHS == double[2])) { // .. etc... } assert(0); // type not supported } should that be split up?
I would say, depends on how you can implement what you need in the shortest way (with lest code-duplication). If one operator works with several types on RHS, but others don't, split the operators. If all operators work the same for same RHS type but different for different RHS types, split the types.
Jun 24 2020