This is a shortened version of some operator overloading code from page 372 
(although some code is from pages before it), sorry for the long post:

module binary_ops;

import std.stdio : writeln;
import std.traits;
import std.exception;

unittest
{
    auto foo = CheckedInt!(int)(5);
    auto bar = CheckedInt!(int)(5);
    
    foo = foo + bar;
    writeln(foo.Value);
}

void main()
{
}
 
struct CheckedInt(N) if (isIntegral!N)
{
    private N value;
    
    this(N value)
    {
        this.value = value;
    }
    
    @property
    auto Value()
    {
        return value;
    }
    
    // addition
    CheckedInt opBinary(string op)(CheckedInt rhs) if (op == "+")
    {
        auto result = value + rhs.value;
        
        enforce(rhs.value >= 0 ? result >= value : result < value);
        return result;
    }
}

I don't understand why he's trying to return result here (unless it was a 
mistake). Result is going to have the type of "private N value", whatever N may 
be, and this is conflicting with the return type which is CheckedInt. So, this 
won't compile.

He has the same returns for subtraction and multiplication, but for others like 
division, shift and bitwise overload he has this:

// division and remainder
    CheckedInt opBinary(string op)(CheckedInt rhs)
    if (op == "/" || op == "%")
    {
        enforce(rhs.value != 0);
        return CheckedInt(mixin("value" ~ op ~ "rhs.value"));
    }

This looks correct. If I change the add overload from the code to this:

// addition
    CheckedInt opBinary(string op)(CheckedInt rhs) if (op == "+")
    {
        auto result = value + rhs.value;
        
        enforce(rhs.value >= 0 ? result >= value : result < value);
        return CheckedInt(mixin("value" ~ op ~ "rhs.value"));
    }

Then the return statement calls a CheckedInt constructor and I get back a 
CheckedInt struct with the right value in the private variable "value".

What I don't understand is how the constructor can be called like that. In my 
example the mixin would convert the code to:

return CheckedInt(10);

But if I ever tried a call like "CheckedInt(10)" in a unittest block, it 
wouldn't work. So how does this magic work?

Reply via email to