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