Page 373 adds another operator overload for use with integral numbers (CheckedInt op Int). But it conflicts with the previos template (CheckedInt op CheckedInt):
module binary_ops; import std.stdio : writeln; import std.traits; import std.exception; unittest { auto foo = CheckedInt!(int)(5); foo + 4; } void main() { } struct CheckedInt(N) if (isIntegral!N) { private N value; public int x; this(N value) { this.value = value; } // Operation with raw numbers CheckedInt opBinary(string op)(N rhs) if (isIntegral!N) { return opBinary!op(CheckedInt(rhs)); } // addition CheckedInt opBinary(string op)(CheckedInt rhs) if (op == "+") { auto result = value + rhs.value; enforce(rhs.value >= 0 ? result >= value : result < value); return CheckedInt(result); } } I get back: binary_ops.d(34): Error: template instance opBinary!(op) matches more than one template declaration, binary_ops.d(32):opBinary(string op) if (isIntegral!(N)) and binary_ops.d(38):opBinary(string op) if (op == "+") One is taking an integral by using a constraint, the other specifically a CheckedInt type. Any clues how they both match? If I remove the first operator overload template then I can't compile, so where's the ambiguity?