Skip to content

Commit e0e5852

Browse files
authored
Merge pull request #3467 from ntrel/opover-examples
[operatoroverloading.dd] Improve examples
2 parents 54bcf8b + 7c8d50f commit e0e5852

File tree

1 file changed

+78
-11
lines changed

1 file changed

+78
-11
lines changed

spec/operatoroverloading.dd

Lines changed: 78 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ $(H2 $(LNAME2 eqcmp, Overloading the Comparison Operators))
369369
$(D opCmp).)
370370

371371
$(P The equality and inequality operators are treated separately
372+
from comparison operators
372373
because while practically all user-defined types can be compared for
373374
equality, only a subset of types have a meaningful ordering. For
374375
example, while it makes sense to determine if two RGB color vectors are
@@ -514,6 +515,28 @@ struct S
514515
version of $(D opEquals). Otherwise, inequalities like $(D a <= b)
515516
will behave inconsistently with equalities like $(D a == b).)
516517

518+
$(SPEC_RUNNABLE_EXAMPLE_RUN
519+
---
520+
struct S
521+
{
522+
int i, j;
523+
int opCmp(ref const S s) const { return (i > s.i) - (i < s.i); } // ignore j
524+
}
525+
526+
S a = {2, 3};
527+
S b = {2, 1};
528+
S c = {3, 0};
529+
assert(a < c);
530+
assert(a <= b);
531+
assert(!(a < b)); // opCmp ignores j
532+
assert(a != b); // generated opEquals tests both i and j members
533+
---
534+
)
535+
536+
$(BEST_PRACTICE Using `(i > s.i) - (i < s.i)` instead of `i - s.i` to
537+
compare integers avoids overflow.)
538+
539+
517540
$(H2 $(LEGACY_LNAME2 FunctionCall, function-call, Function Call Operator Overloading $(D f())))
518541

519542
$(P The function call operator, $(D ()), can be overloaded by
@@ -548,20 +571,24 @@ $(H2 $(LEGACY_LNAME2 FunctionCall, function-call, Function Call Operator Overloa
548571
so that it takes priority over $(D opCall) in $(D Type(...)) syntax.
549572
)
550573

574+
$(SPEC_RUNNABLE_EXAMPLE_RUN
551575
-------
552576
struct Multiplier
553577
{
554578
int factor;
555579
this(int num) { factor = num; }
556580
int opCall(int value) { return value * factor; }
557581
}
558-
void test()
582+
583+
void main()
559584
{
560585
Multiplier m = Multiplier(10); // invoke constructor
586+
assert(m.factor == 10);
561587
int result = m(5); // invoke opCall
562588
assert(result == 50);
563589
}
564590
-------
591+
)
565592

566593
$(H3 $(LNAME2 static-opcall, Static opCall))
567594

@@ -729,6 +756,21 @@ a $(METACODE op)= b
729756
a.opOpAssign!($(METACODE "op"))(b)
730757
---
731758

759+
Example:
760+
$(SPEC_RUNNABLE_EXAMPLE_RUN
761+
---
762+
struct S
763+
{
764+
int i;
765+
void opOpAssign(string op: "+")(int rhs) { i += rhs; }
766+
}
767+
768+
S s = {2};
769+
s += 3;
770+
assert(s.i == 5);
771+
---
772+
)
773+
732774
$(H3 $(LNAME2 index_op_assignment, Index Op Assignment Operator Overloading))
733775

734776
$(P If the left hand side of an $(I op)= is an index expression on
@@ -823,6 +865,7 @@ $(H3 $(LEGACY_LNAME2 Slice, slice, Slice Operator Overloading))
823865
$(P To overload $(D a[]), simply define $(D opIndex) with no parameters:
824866
)
825867

868+
$(SPEC_RUNNABLE_EXAMPLE_RUN
826869
-----
827870
struct S
828871
{
@@ -832,25 +875,49 @@ struct S
832875
return impl[];
833876
}
834877
}
835-
void test()
878+
879+
void main()
836880
{
837881
auto s = S([1,2,3]);
838-
auto t = s[]; // calls s.opIndex()
882+
int[] t = s[]; // calls s.opIndex()
839883
assert(t == [1,2,3]);
840884
}
841885
-----
886+
)
842887

843-
$(P To overload array indexing of the form $(D a[)$(SLICE)$(D ,) ...$(D ]),
888+
$(P To overload array slicing of the form $(D a[)$(SLICE)$(D ]),
844889
two steps are needed. First, the expressions of the form $(SLICE) are
845-
translated via $(D opSlice) into user-defined objects that encapsulate
846-
the endpoints $(I i) and $(I j). Then these user-defined objects are
847-
passed to $(D opIndex) to perform the actual slicing. This design was
890+
translated via $(D opSlice!0) into objects that encapsulate
891+
the endpoints $(I i) and $(I j). Then these objects are
892+
passed to $(D opIndex) to perform the actual slicing.)
893+
894+
$(SPEC_RUNNABLE_EXAMPLE_RUN
895+
---
896+
struct S
897+
{
898+
int[] impl;
899+
900+
int[] opSlice(size_t dim: 0)(size_t i, size_t j)
901+
{
902+
return impl[i..j];
903+
}
904+
int[] opIndex()(int[] slice) { return slice; }
905+
}
906+
907+
void main()
908+
{
909+
auto s = S([1, 2, 3]);
910+
int[] t = s[0..2]; // calls s.opIndex(s.opSlice(0, 2))
911+
assert(t == [1, 2]);
912+
}
913+
---
914+
)
915+
916+
$(P This design was
848917
chosen in order to support mixed indexing and slicing in
849918
multidimensional arrays; for example, in translating expressions like
850919
$(D arr[1, 2..3, 4]).
851-
)
852-
853-
$(P More precisely, an expression of the form $(D arr[)$(ARGUMENTS)$(D ])
920+
More precisely, an expression of the form $(D arr[)$(ARGUMENTS)$(D ])
854921
is translated into $(D arr.opIndex$(LPAREN))$(ARGUMENTS2)$(D $(RPAREN)).
855922
Each argument $(I b)$(SUBSCRIPT i) can be either a single expression,
856923
in which case it is passed directly as the corresponding argument $(I
@@ -911,7 +978,7 @@ __tmp.opIndexAssign(c, 1, __tmp.opSlice!1(2,3), __tmp.opDollar!2 - 1);
911978
once.
912979
)
913980

914-
$(P For backward compatibility, $(D a[]) and $(D a[)$(SLICE)$(D ]) can
981+
$(NOTE For backward compatibility, $(D a[]) and $(D a[)$(SLICE)$(D ]) can
915982
also be overloaded by implementing $(D opSlice()) with no arguments and
916983
$(D opSlice$(LPAREN))$(SLICE2)$(D $(RPAREN)) with two arguments,
917984
respectively. This only applies for one-dimensional slicing, and dates

0 commit comments

Comments
 (0)