1 import std.traits : isUnsigned; 2 3 static struct MyHook 4 { 5 static bool thereWereErrors; 6 static bool hookOpEquals(L, R)(L lhs, R rhs) 7 { 8 if (lhs != rhs) return false; 9 static if (isUnsigned!L && !isUnsigned!R) 10 { 11 if (lhs > 0 && rhs < 0) thereWereErrors = true; 12 } 13 else static if (isUnsigned!R && !isUnsigned!L) 14 if (lhs < 0 && rhs > 0) thereWereErrors = true; 15 // Preserve built-in behavior. 16 return true; 17 } 18 } 19 auto a = checked!MyHook(-42); 20 assert(a == uint(-42)); 21 assert(MyHook.thereWereErrors); 22 MyHook.thereWereErrors = false; 23 assert(checked!MyHook(uint(-42)) == -42); 24 assert(MyHook.thereWereErrors); 25 static struct MyHook2 26 { 27 static bool hookOpEquals(L, R)(L lhs, R rhs) 28 { 29 return lhs == rhs; 30 } 31 } 32 MyHook.thereWereErrors = false; 33 assert(checked!MyHook2(uint(-42)) == a); 34 // Hook on left hand side takes precedence, so no errors 35 assert(!MyHook.thereWereErrors);
Compares this against rhs for equality. If Hook defines hookOpEquals, the function forwards to hook.hookOpEquals(get, rhs). Otherwise, the result of the built-in operation get == rhs is returned.
If U is also an instance of Checked, both hooks (left- and right-hand side) are introspected for the method hookOpEquals. If both define it, priority is given to the left-hand side.