@@ -785,100 +785,6 @@ $(H2 $(LEGACY_LNAME2 ArrayOps, array-ops, Array Indexing and Slicing Operators O
785
785
These may be combined to implement multidimensional arrays.
786
786
)
787
787
788
- $(P The code example below shows a simple implementation of a
789
- 2-dimensional array with overloaded indexing and slicing operators. The
790
- explanations of the various constructs employed are given in the
791
- sections following.)
792
-
793
- -------
794
- struct Array2D(E)
795
- {
796
- E[] impl;
797
- int stride;
798
- int width, height;
799
-
800
- this(int width, int height, E[] initialData = [])
801
- {
802
- impl = initialData;
803
- this.stride = this.width = width;
804
- this.height = height;
805
- impl.length = width * height;
806
- }
807
-
808
- // Index a single element, e.g., arr[0, 1]
809
- ref E opIndex(int i, int j) { return impl[i + stride*j]; }
810
-
811
- // Array slicing, e.g., arr[1..2, 1..2], arr[2, 0..$], arr[0..$, 1].
812
- Array2D opIndex(int[2] r1, int[2] r2)
813
- {
814
- Array2D result;
815
-
816
- auto startOffset = r1[0] + r2[0]*stride;
817
- auto endOffset = r1[1] + (r2[1] - 1)*stride;
818
- result.impl = this.impl[startOffset .. endOffset];
819
-
820
- result.stride = this.stride;
821
- result.width = r1[1] - r1[0];
822
- result.height = r2[1] - r2[0];
823
-
824
- return result;
825
- }
826
- auto opIndex(int[2] r1, int j) { return opIndex(r1, [j, j+1]); }
827
- auto opIndex(int i, int[2] r2) { return opIndex([i, i+1], r2); }
828
-
829
- // Support for `x..y` notation in slicing operator for the given dimension.
830
- int[2] opSlice(size_t dim)(int start, int end)
831
- if (dim >= 0 && dim < 2)
832
- in { assert(start >= 0 && end <= this.opDollar!dim); }
833
- do
834
- {
835
- return [start, end];
836
- }
837
-
838
- // Support `$` in slicing notation, e.g., arr[1..$, 0..$-1].
839
- @property int opDollar(size_t dim : 0)() { return width; }
840
- @property int opDollar(size_t dim : 1)() { return height; }
841
- }
842
-
843
- unittest
844
- {
845
- auto arr = Array2D!int(4, 3, [
846
- 0, 1, 2, 3,
847
- 4, 5, 6, 7,
848
- 8, 9, 10, 11
849
- ]);
850
-
851
- // Basic indexing
852
- assert(arr[0, 0] == 0);
853
- assert(arr[1, 0] == 1);
854
- assert(arr[0, 1] == 4);
855
-
856
- // Use of opDollar
857
- assert(arr[$-1, 0] == 3);
858
- assert(arr[0, $-1] == 8); // Note the value of $ differs by dimension
859
- assert(arr[$-1, $-1] == 11);
860
-
861
- // Slicing
862
- auto slice1 = arr[1..$, 0..$];
863
- assert(slice1[0, 0] == 1 && slice1[1, 0] == 2 && slice1[2, 0] == 3 &&
864
- slice1[0, 1] == 5 && slice1[1, 1] == 6 && slice1[2, 1] == 7 &&
865
- slice1[0, 2] == 9 && slice1[1, 2] == 10 && slice1[2, 2] == 11);
866
-
867
- auto slice2 = slice1[0..2, 1..$];
868
- assert(slice2[0, 0] == 5 && slice2[1, 0] == 6 &&
869
- slice2[0, 1] == 9 && slice2[1, 1] == 10);
870
-
871
- // Thin slices
872
- auto slice3 = arr[2, 0..$];
873
- assert(slice3[0, 0] == 2 &&
874
- slice3[0, 1] == 6 &&
875
- slice3[0, 2] == 10);
876
-
877
- auto slice4 = arr[0..3, 2];
878
- assert(slice4[0, 0] == 8 && slice4[1, 0] == 9 && slice4[2, 0] == 10);
879
- }
880
- -------
881
-
882
788
$(H3 $(LEGACY_LNAME2 Array, array, Index Operator Overloading))
883
789
884
790
$(P Expressions of the form $(D arr[)$(ARGUMENTS)$(D ]) are translated
@@ -1097,6 +1003,104 @@ arr.opIndex(__tmp1 - sqrt(__tmp1), 0, __tmp2 - 1);
1097
1003
than one argument.
1098
1004
)
1099
1005
1006
+ $(H3 $(LNAME2 index-slicing-example, Complete Example))
1007
+
1008
+ $(P The code example below shows a simple implementation of a
1009
+ 2-dimensional array with overloaded indexing and slicing operators. The
1010
+ explanations of the various constructs employed are given in the
1011
+ sections following.)
1012
+
1013
+ $(SPEC_RUNNABLE_EXAMPLE_RUN
1014
+ -------
1015
+ struct Array2D(E)
1016
+ {
1017
+ E[] impl;
1018
+ int stride;
1019
+ int width, height;
1020
+
1021
+ this(int width, int height, E[] initialData = [])
1022
+ {
1023
+ impl = initialData;
1024
+ this.stride = this.width = width;
1025
+ this.height = height;
1026
+ impl.length = width * height;
1027
+ }
1028
+
1029
+ // Index a single element, e.g., arr[0, 1]
1030
+ ref E opIndex(int i, int j) { return impl[i + stride*j]; }
1031
+
1032
+ // Array slicing, e.g., arr[1..2, 1..2], arr[2, 0..$], arr[0..$, 1].
1033
+ Array2D opIndex(int[2] r1, int[2] r2)
1034
+ {
1035
+ Array2D result;
1036
+
1037
+ auto startOffset = r1[0] + r2[0]*stride;
1038
+ auto endOffset = r1[1] + (r2[1] - 1)*stride;
1039
+ result.impl = this.impl[startOffset .. endOffset];
1040
+
1041
+ result.stride = this.stride;
1042
+ result.width = r1[1] - r1[0];
1043
+ result.height = r2[1] - r2[0];
1044
+
1045
+ return result;
1046
+ }
1047
+ auto opIndex(int[2] r1, int j) { return opIndex(r1, [j, j+1]); }
1048
+ auto opIndex(int i, int[2] r2) { return opIndex([i, i+1], r2); }
1049
+
1050
+ // Support for `x..y` notation in slicing operator for the given dimension.
1051
+ int[2] opSlice(size_t dim)(int start, int end)
1052
+ if (dim >= 0 && dim < 2)
1053
+ in { assert(start >= 0 && end <= this.opDollar!dim); }
1054
+ do
1055
+ {
1056
+ return [start, end];
1057
+ }
1058
+
1059
+ // Support `$` in slicing notation, e.g., arr[1..$, 0..$-1].
1060
+ @property int opDollar(size_t dim : 0)() { return width; }
1061
+ @property int opDollar(size_t dim : 1)() { return height; }
1062
+ }
1063
+
1064
+ void main()
1065
+ {
1066
+ auto arr = Array2D!int(4, 3, [
1067
+ 0, 1, 2, 3,
1068
+ 4, 5, 6, 7,
1069
+ 8, 9, 10, 11
1070
+ ]);
1071
+
1072
+ // Basic indexing
1073
+ assert(arr[0, 0] == 0);
1074
+ assert(arr[1, 0] == 1);
1075
+ assert(arr[0, 1] == 4);
1076
+
1077
+ // Use of opDollar
1078
+ assert(arr[$-1, 0] == 3);
1079
+ assert(arr[0, $-1] == 8); // Note the value of $ differs by dimension
1080
+ assert(arr[$-1, $-1] == 11);
1081
+
1082
+ // Slicing
1083
+ auto slice1 = arr[1..$, 0..$];
1084
+ assert(slice1[0, 0] == 1 && slice1[1, 0] == 2 && slice1[2, 0] == 3 &&
1085
+ slice1[0, 1] == 5 && slice1[1, 1] == 6 && slice1[2, 1] == 7 &&
1086
+ slice1[0, 2] == 9 && slice1[1, 2] == 10 && slice1[2, 2] == 11);
1087
+
1088
+ auto slice2 = slice1[0..2, 1..$];
1089
+ assert(slice2[0, 0] == 5 && slice2[1, 0] == 6 &&
1090
+ slice2[0, 1] == 9 && slice2[1, 1] == 10);
1091
+
1092
+ // Thin slices
1093
+ auto slice3 = arr[2, 0..$];
1094
+ assert(slice3[0, 0] == 2 &&
1095
+ slice3[0, 1] == 6 &&
1096
+ slice3[0, 2] == 10);
1097
+
1098
+ auto slice4 = arr[0..3, 2];
1099
+ assert(slice4[0, 0] == 8 && slice4[1, 0] == 9 && slice4[2, 0] == 10);
1100
+ }
1101
+ -------
1102
+ )
1103
+
1100
1104
1101
1105
$(H2 $(LEGACY_LNAME2 Dispatch, dispatch, Forwarding))
1102
1106
0 commit comments