Skip to content

Commit 6f88980

Browse files
committed
[operatoroverloading.dd] Improve examples
Add opCmp example. Make opCall example runnable. Add opOpAssign example. Make opIndex() example runnable. Add example for `s.opIndex(s.opSlice(...))`, tweak paragraph.
1 parent 6c72655 commit 6f88980

File tree

1 file changed

+71
-10
lines changed

1 file changed

+71
-10
lines changed

spec/operatoroverloading.dd

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,23 @@ struct S
514514
version of $(D opEquals). Otherwise, inequalities like $(D a <= b)
515515
will behave inconsistently with equalities like $(D a == b).)
516516

517+
$(SPEC_RUNNABLE_EXAMPLE_RUN
518+
---
519+
struct S
520+
{
521+
int i, j;
522+
int opCmp(ref const S s) const { return i - s.i; } // ignore j
523+
}
524+
525+
S a = {2, 3};
526+
S b = {2, 1};
527+
assert(a <= b);
528+
assert(!(a < b));
529+
assert(a != b); // generated opEquals tests both i and j members
530+
---
531+
)
532+
533+
517534
$(H2 $(LEGACY_LNAME2 FunctionCall, function-call, Function Call Operator Overloading $(D f())))
518535

519536
$(P The function call operator, $(D ()), can be overloaded by
@@ -548,20 +565,24 @@ $(H2 $(LEGACY_LNAME2 FunctionCall, function-call, Function Call Operator Overloa
548565
so that it takes priority over $(D opCall) in $(D Type(...)) syntax.
549566
)
550567

568+
$(SPEC_RUNNABLE_EXAMPLE_RUN
551569
-------
552570
struct Multiplier
553571
{
554572
int factor;
555573
this(int num) { factor = num; }
556574
int opCall(int value) { return value * factor; }
557575
}
558-
void test()
576+
577+
void main()
559578
{
560579
Multiplier m = Multiplier(10); // invoke constructor
580+
assert(m.factor == 10);
561581
int result = m(5); // invoke opCall
562582
assert(result == 50);
563583
}
564584
-------
585+
)
565586

566587
$(H3 $(LNAME2 static-opcall, Static opCall))
567588

@@ -729,6 +750,21 @@ a $(METACODE op)= b
729750
a.opOpAssign!($(METACODE "op"))(b)
730751
---
731752

753+
Example:
754+
$(SPEC_RUNNABLE_EXAMPLE_RUN
755+
---
756+
struct S
757+
{
758+
int i;
759+
void opOpAssign(string op: "+")(int rhs) { i += rhs; }
760+
}
761+
762+
S s = {2};
763+
s += 3;
764+
assert(s.i == 5);
765+
---
766+
)
767+
732768
$(H3 $(LNAME2 index_op_assignment, Index Op Assignment Operator Overloading))
733769

734770
$(P If the left hand side of an $(I op)= is an index expression on
@@ -917,6 +953,7 @@ $(H3 $(LEGACY_LNAME2 Slice, slice, Slice Operator Overloading))
917953
$(P To overload $(D a[]), simply define $(D opIndex) with no parameters:
918954
)
919955

956+
$(SPEC_RUNNABLE_EXAMPLE_RUN
920957
-----
921958
struct S
922959
{
@@ -926,25 +963,49 @@ struct S
926963
return impl[];
927964
}
928965
}
929-
void test()
966+
967+
void main()
930968
{
931969
auto s = S([1,2,3]);
932-
auto t = s[]; // calls s.opIndex()
970+
int[] t = s[]; // calls s.opIndex()
933971
assert(t == [1,2,3]);
934972
}
935973
-----
974+
)
936975

937-
$(P To overload array indexing of the form $(D a[)$(SLICE)$(D ,) ...$(D ]),
976+
$(P To overload array slicing of the form $(D a[)$(SLICE)$(D ]),
938977
two steps are needed. First, the expressions of the form $(SLICE) are
939-
translated via $(D opSlice) into user-defined objects that encapsulate
978+
translated via $(D opSlice!0) into user-defined objects that encapsulate
940979
the endpoints $(I i) and $(I j). Then these user-defined objects are
941-
passed to $(D opIndex) to perform the actual slicing. This design was
980+
passed to $(D opIndex) to perform the actual slicing.)
981+
982+
$(SPEC_RUNNABLE_EXAMPLE_RUN
983+
---
984+
struct S
985+
{
986+
int[] impl;
987+
988+
int[] opSlice(size_t dim: 0)(size_t i, size_t j)
989+
{
990+
return impl[i..j];
991+
}
992+
int[] opIndex()(int[] slice) { return slice; }
993+
}
994+
995+
void main()
996+
{
997+
auto s = S([1, 2, 3]);
998+
int[] t = s[0..2]; // calls s.opIndex(s.opSlice(0, 2))
999+
assert(t == [1, 2]);
1000+
}
1001+
---
1002+
)
1003+
1004+
$(P This design was
9421005
chosen in order to support mixed indexing and slicing in
9431006
multidimensional arrays; for example, in translating expressions like
9441007
$(D arr[1, 2..3, 4]).
945-
)
946-
947-
$(P More precisely, an expression of the form $(D arr[)$(ARGUMENTS)$(D ])
1008+
More precisely, an expression of the form $(D arr[)$(ARGUMENTS)$(D ])
9481009
is translated into $(D arr.opIndex$(LPAREN))$(ARGUMENTS2)$(D $(RPAREN)).
9491010
Each argument $(I b)$(SUBSCRIPT i) can be either a single expression,
9501011
in which case it is passed directly as the corresponding argument $(I
@@ -1005,7 +1066,7 @@ __tmp.opIndexAssign(c, 1, __tmp.opSlice!1(2,3), __tmp.opDollar!2 - 1);
10051066
once.
10061067
)
10071068

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

0 commit comments

Comments
 (0)