Skip to content

Commit 1cc32f3

Browse files
authored
[spec/expression] Document class comparison with object.__cmp (#4225)
Fixes #4224. Also briefly describe struct comparison. Update example - comparing null is not a runtime error.
1 parent d8fcb7e commit 1cc32f3

File tree

2 files changed

+29
-16
lines changed

2 files changed

+29
-16
lines changed

spec/expression.dd

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -870,33 +870,42 @@ $(H3 $(LEGACY_LNAME2 floating_point_comparisons, floating-point-comparisons, Flo
870870
there are other floating-point values for NaN produced at runtime.
871871
Use $(REF isNaN, std,math,traits) to handle all of them.)
872872

873-
$(H3 $(LEGACY_LNAME2 class_comparisons, class-comparisons, Class Comparisons))
873+
$(H3 $(LEGACY_LNAME2 class_comparisons, class-comparisons, Class and Struct Comparisons))
874874

875-
$(P For class objects, *EqualExpression* and *RelExpression* compare the
876-
*contents* of the objects. Therefore, comparing against
877-
a $(CODE null) class reference is invalid, as $(CODE null) has no contents.)
875+
$(P For struct objects, a *RelExpression* performs a comparison which first
876+
evaluates $(DDSUBLINK spec/operatoroverloading, compare, a matching `opCmp`
877+
method) call.)
878878

879-
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
879+
$(P For class references, a *RelExpression* performs a comparison which first
880+
evaluates to an `int` which is either:)
881+
882+
- `0` if the two object references are identical
883+
- `-1` if the left-hand expression is `null`
884+
- `1` if the right-hand expression is `null`
885+
- the result of $(DDSUBLINK spec/operatoroverloading, compare,
886+
a matching `opCmp`) call
887+
888+
$(SPEC_RUNNABLE_EXAMPLE_RUN
880889
---
881-
class C {}
890+
class C
891+
{
892+
override int opCmp(Object o) { assert(0); }
893+
}
882894

883-
void fun()
895+
void main()
884896
{
885897
C c;
886898
//if (c < null) {} // compile-time error
887899
assert(c is null);
888-
if (c > new C) {} // runtime error
900+
assert(c < new C); // C.opCmp is not called
889901
}
890902
---
891903
)
892904

893-
$(P For class objects, the result of `Object.opCmp()` forms the left
894-
operand, and `0` forms the right operand. The result of an
895-
*EqualExpression* or *RelExpression* `(o1 op o2)` is:)
896-
897-
---
898-
(o1.opCmp(o2) op 0)
899-
---
905+
$(P Secondly, for class and struct objects, the evaluated `int` is compared
906+
against zero using the given operator, which forms the result of the
907+
*RelExpression*. For more information, see
908+
$(DDSUBLINK spec/operatoroverloading, compare, `opCmp`).)
900909

901910

902911
$(H2 $(LNAME2 in_expressions, In Expressions))

spec/operatoroverloading.dd

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,11 @@ $(OL
487487

488488
$(H3 $(LNAME2 compare, Overloading $(D <), $(D <)$(D =), $(D >), and $(D >)$(D =)))
489489

490-
$(P Comparison operations are rewritten as follows:)
490+
$(P Class references are first $(DDSUBLINK spec/expression, class-comparisons,
491+
compared by reference). If they refer to different objects and neither is `null`,
492+
they are then compared by calling a matching `opCmp` method, as for structs.)
493+
494+
$(P Struct comparison operations are rewritten as follows:)
491495

492496
$(TABLE2 Rewriting of comparison operations,
493497
$(THEAD comparison, rewrite 1, rewrite 2)

0 commit comments

Comments
 (0)