Shortcomings of D-Style Fused Operator Overloading
Ahmet Sait
nightmarex1337 at hotmail.com
Fri Jul 7 09:18:38 UTC 2023
For the past few weeks I've been working on a simple compiler for
my grad project, and I was trying to make use of operator
overloading in some of my types named Interval and Constant.
Interval supposed to be a type that supports all kinds of
arithmetic operations with another Interval which would be used
for implementing [Value Range
Propagation](https://digitalmars.com/articles/b62.html).
Now to the operator overloading part. As I was trying to
implement the Interval type, I realized an interesting issue. The
way operator overloading works in D is with a unified `opCmp()`
method that returns -1, 0 or 1 depending on the inequality, and
`a < b` gets lowered to `a.opCmp(b) < 0`. However, implementing
inequality correctly for intervals requires us to know the exact
operator used.
Let's define two intervals x and y:
{x ∈ ℝ │ a ≤ x ≤ b}
{y ∈ ℝ │ c ≤ y ≤ d}
And the inequality operators:
```
x < y = ⎧ 1 if b < c
⎨
⎩ 0 otherwise
x ≤ y = ⎧ 1 if b ≤ c
⎨
⎩ 0 otherwise
x > y = ⎧ 1 if a > d
⎨
⎩ 0 otherwise
x ≥ y = ⎧ 1 if a ≥ d
⎨
⎩ 0 otherwise
```
Exercise: Write an `opCmp()` method that implements the rules
above for `struct Interval { int lower, upper; }`. (Hint: It's
not possible.)
I didn't fully implement or used this Interval type I was cooking
because I was running out of time for the project, so I opted for
something simpler which is to just do constant folding, hence the
Constant type. Constant is basically a tagged union like
`bool|integer|real`, and it doesn't have the fuzzy ordering
issues like in the Interval type above.
For Constant, I wanted to implement all unary operators, one of
which is logical not `!`. The only way to do this in D is by
writing a `bool opCast(T:bool)`, except I don't want to return a
bool! I want to return another Constant that represents the
logical inverse of what the current Constant contains, and be
able write this:
```
Constant c2 = !c1; // Lowered to !c1.opCast!bool
```
As you can guess, returning a Constant from `opCast()` instead of
`bool` results in this error message:
> Error: cannot implicitly convert expression `c1.opCast()` of
> type `Constant` to `bool`
***
Now you might be thinking, I could just define a bunch of regular
functions such as `logicalNot()`, `lowerOrEquals()` etc. and you
would be right (which is what I ended up doing anyway). I guess
the point here is that the way D merges these operators to reduce
potential bugs actually end up making certain things
inexpressible naturally.
So what do you guys think? Would you say distinct operators are
better?
More information about the Digitalmars-d
mailing list