@@ -18,8 +18,8 @@ private import core.int128;
1818
1919public struct Int128
2020{
21- @safe pure nothrow @nogc :
22-
21+ @safe pure nothrow @nogc
22+ {
2323 Cent data; // / core.int128.Cent
2424
2525 /* ***************
@@ -253,23 +253,32 @@ public struct Int128
253253 mixin (" this = this " ~ op ~ " op2;" );
254254 return this ;
255255 }
256+ } // @safe pure nothrow @nogc
256257
257- /* * support signed arithmentic comparison operators < <= > >=
258+ /* * support arithmentic comparison operators < <= > >=
258259 * Params: op2 = right hand operand
259260 * Returns: -1 for less than, 0 for equals, 1 for greater than
260261 */
261- int opCmp (Int128 op2) const
262+ int opCmp (Int128 op2) const @nogc nothrow pure @safe
262263 {
263264 return this == op2 ? 0 : gt(this .data, op2.data) * 2 - 1 ;
264265 }
265266
266- /* * support signed arithmentic comparison operators < <= > >=
267- * Params: op2 = right hand operand
268- * Returns: -1 for less than, 0 for equals, 1 for greater than
269- */
270- int opCmp (long op2) const
267+ // / ditto
268+ int opCmp (Int)(const Int op2) const @nogc nothrow pure @safe
269+ if (is (Int : long ) && __traits(isIntegral, Int))
271270 {
272- return opCmp (Int128(0 , op2));
271+ static if (__traits(isUnsigned, Int))
272+ return opCmp (Int128(0 , op2));
273+ else
274+ return opCmp (Int128((cast (long ) op2) >> 63 , op2));
275+ }
276+
277+ // / ditto
278+ int opCmp (IntLike)(auto ref IntLike op2) const
279+ if (is (IntLike : long ) && ! __traits(isIntegral, IntLike))
280+ {
281+ return opCmp (__traits(getMember, op2, __traits(getAliasThis, IntLike)[0 ]));
273282 }
274283
275284 enum min = Int128(long .min, 0 ); // / minimum value
@@ -372,3 +381,34 @@ unittest
372381 c = Int128(- 1L );
373382 assert (c == - 1L );
374383}
384+
385+ @system unittest
386+ {
387+ alias Seq (T... ) = T;
388+ Int128 c = Int128(- 1L );
389+ assert (c.opCmp (- 1L ) == 0 );
390+ // To avoid regression calling opCmp with any integral type needs to
391+ // work without the compiler complaining "opCmp called with argument
392+ // X matches both <...>".
393+ static foreach (Int; Seq! (long , int , short , byte , ulong , uint , ushort , ubyte , dchar , wchar , char ))
394+ assert (c < Int.max);
395+ static foreach (Int; Seq! (int , short , byte ))
396+ assert (c.opCmp (Int(- 1 )) == 0 );
397+ assert (c < true );
398+ // To avoid regression calling opCmp with any type that converts to an
399+ // integral type through alias this needs to work regardless of whether
400+ // the alias is safe/pure/nothrow/nogc and regardless of whether the
401+ // type has a disabled postblit.
402+ static struct Wrapped (T)
403+ {
404+ T value;
405+ uint count;
406+ T get () @system { ++ count; return value; } // not const
407+ alias get this ;
408+ @disable this (this ); // no implicit copies
409+ }
410+ assert (c.opCmp (Wrapped! long (- 1 )) == 0 );
411+ auto w = Wrapped! ulong (ulong .max);
412+ w.count++ ; // avoid invalid D-Scanner message that w could have been declared const
413+ assert (c < w);
414+ }
0 commit comments