what is the proper syntax to inherit a pair of nested classes using templates ?
I am needing pairs of specific nested classes with already-coded collection management; eg: classComputers having nested classComputer as following (as seen by client code that is): - classComputer ← objComputers.add("ID1", "workstation # 1") - classComputer ← objComputers.add("ID2", "workstation # 2") - classComputer ← objComputers.add("ID3", "workstation # 3") - classComputer ← objComputers.first - classComputer ← objComputers.last - classComputer ← objComputers[2].previous - classComputer ← objComputers[2].next - string ← objComputers[2].name - string ← objComputers["ID2"].name - classComputer ← objComputers["ID2"].next - classComputer ← objComputers["ID2"].previous - size_t ← objComputers.count - bool ← objComputers.empty - bool ← objComputers.remove("ID3") - bool ← objComputers.removeAll() - classComputers ← objComputers.filterByWhatever("...") ... extended functionality like this specifically implemented on-demand by client code ... so classComputers should inherit the collection management infrastructure (ie: the store itself and associated properties/methods to handle it) while classComputer should inherit collection access with this.outer (or the like) ... now let's see my implementation: ```d abstract public class classCollectionItems( typeItems, typeItem ) { /// (1) given type for collection items; eg: classComputers /// (2) given type for collection item; eg: classComputer typeItems lhs; typeItems rhs; int opApply(int delegate(typeItem) dg) { /// boilerplate code to handle the class's default collection int lintResult = 0; /// must find a better name foreach (lobjItem; items) { /// looping over the computers starting in current node lintResult = dg(lobjItem); /// passing single object to the loop body if (lintResult != 0) { break; } } if (lintResult != 0 && lhs ! is null) { lintResult = lhs.opApply(dg); } /// recursing child nodes if (lintResult != 0 && rhs ! is null) { lintResult = rhs.opApply(dg); } /// recursing child nodes return lintResult; } final public typeItem add(in string lstrID) { return false; }; final public bool remove(in string lstrID) { return false; }; final public bool removeAll() { this.items.length = cast(size_t) 0; return this.items.length == cast(size_t) 0; }; final public @property const bool empty() { return this.items.empty; } final public @property const size_t count() { return this.count1; } final public @property const size_t count0() { return this.items.empty ? cast(size_t) 0 : this.items.length - cast(size_t) 1; } final public @property const size_t count1() { return this.items.empty ? cast(size_t) 0 : this.items.length; } final public @property typeItem first() { return null; } final public @property typeItem last() { return null; } abstract public class classCollectionItem { private size_t pintPosition0 = cast(size_t) 0; /// keep in mind that array positions are zero-based final public @property const size_t position0() { return this.pintPosition0; } final public @property const size_t position1() { return this.pintPosition0 + cast(size_t) 1; } final public @property const size_t countAbove() { return this.outer.items.empty ? cast(size_t) 0 : this.pintPosition0; } final public @property const size_t countBelow() { return this.outer.items.empty ? cast(size_t) 0 : this.outer.length - this.pintPosition0 - cast(size_t) 1; } /// eg: for position0=0 → countAbove=0=(position0=0) & countBelow=2=(length=3)-(position0=0)-1 /// eg: for position0=1 → countAbove=1=(position0=1) & countBelow=1=(length=3)-(position0=1)-1 /// eg: for position0=2 → countAbove=2=(position0=2) & countBelow=0=(length=3)-(position0=2)-1 final public @property typeItem first() { return this.outer.items.empty ? null : this.outer.items[cast(size_t) 0]; } final public @property typeItem previous() { return this.outer.items.empty || this.countAbove == cast(size_t) 0 ? null : this.outer.items[this.pintPosition0 - cast(size_t) 1]; } final public @property typeItem next() { return this.outer.items.empty || this.countBelow == cast(size_t) 0 ? null : this.outer.items[this.position0 + cast(size_t) 1]; } final public @property typeItem last() { return this.outer.items.empty ? null : this.outer.items[this.outer.items.length - cast(size_t) 1]; } } } ``` ... so far so good, now, when I code my specific classes I am **not sure which is the correct syntax to inherit the base pair**: ```d public class classComputers : classCollectionItems!(classComputers, classComputers.classComputer) { /// seems logical to me public class classComputer {} public class classComputer : classCollectionItem {} public class classComputer : classCollectionItems!(classComputers, classComputers.classComputer).classCollectionItem {} } ```
Re: Classes and templates
On Monday, 31 October 2016 at 22:33:11 UTC, John Colvin wrote: On Monday, 31 October 2016 at 19:24:46 UTC, Hefferman wrote: Hello, I've been trying to implement a class for sorting which accepts arrays which "different" data types. Hard to describe, here's my example (filename sorting.d): [...] Glad to see you're getting helpful responses here, but just an FYI: https://forum.dlang.org/group/learn would be a more appropriate forum for questions like this. Thanks to all for replying! @J.C.: I'll keep it in mind for the next time.
Re: Classes and templates
On Monday, 31 October 2016 at 19:24:46 UTC, Hefferman wrote: Hello, I've been trying to implement a class for sorting which accepts arrays which "different" data types. Hard to describe, here's my example (filename sorting.d): [...] Glad to see you're getting helpful responses here, but just an FYI: https://forum.dlang.org/group/learn would be a more appropriate forum for questions like this.
Re: Classes and templates
On Monday, 31 October 2016 at 20:25:18 UTC, Hefferman wrote: for (uint k = 1; k < n; k++) { if (a[k-1] > a[k]) { T tmp = a[k]; a[k] = a[k+1]; a[k+1] = tmp; sorted = false; } } n--; } while (!sorted); } } [/code] It gives a Range Violation upon executing, but I guess it's part of the algorithm The value of n is array length, so k reaches (n - 1), therefore k+1 gives you n which is out of bounds.
Re: Classes and templates
On Monday, 31 October 2016 at 20:20:09 UTC, Meta wrote: [...] You can't use an un-instantiated template as a type anyway, unlike Java. There the above is illegal because of `BubbleSort b = ...`. The symbol BubbleSort by itself is not a type; you have to instantiate it with template arguments to create a type. So you *could* do it like this: BubbleSort!(typeof(arr)) b = new BubbleSort!(typeof(arr)); But that's too verbose. There's need need to repeat ourselves. You can instead use `auto` and omit the type of `b`, which will be inferred from the right hand side: auto b = new BubbleSort!(typeof(arr)); Thanks! This compiled just fine... [code] import std.random; import std.stdio; void main() { immutable uint N = 10_000; double[] arr = new double[](N); for (uint k = 0; k < N; k++) arr[k] = uniform(0, N); auto b = new BubbleSort!(typeof(arr)); b.Sort(arr); } public class BubbleSort(T) { private T[] a; private uint n; public void Sort(T)(T[] a) { n = a.length; bubblesort(); } private void bubblesort() { bool sorted; do { sorted = true; for (uint k = 1; k < n; k++) { if (a[k-1] > a[k]) { T tmp = a[k]; a[k] = a[k+1]; a[k+1] = tmp; sorted = false; } } n--; } while (!sorted); } } [/code] It gives a Range Violation upon executing, but I guess it's part of the algorithm
Re: Classes and templates
On Monday, 31 October 2016 at 20:06:22 UTC, Hefferman wrote: On Monday, 31 October 2016 at 19:43:57 UTC, Adam D. Ruppe wrote: On Monday, 31 October 2016 at 19:24:46 UTC, Hefferman wrote: Give a template type when crating it new BubbleSort!(string) for example Is it possible to create this using "typeof"? E. g. "BubbleSort b = new BubbleSort!(typeof(arr));" Compilation fails with that line You can't use an un-instantiated template as a type anyway, unlike Java. There the above is illegal because of `BubbleSort b = ...`. The symbol BubbleSort by itself is not a type; you have to instantiate it with template arguments to create a type. So you *could* do it like this: BubbleSort!(typeof(arr)) b = new BubbleSort!(typeof(arr)); But that's too verbose. There's need need to repeat ourselves. You can instead use `auto` and omit the type of `b`, which will be inferred from the right hand side: auto b = new BubbleSort!(typeof(arr));
Re: Classes and templates
On Monday, 31 October 2016 at 19:43:57 UTC, Adam D. Ruppe wrote: On Monday, 31 October 2016 at 19:24:46 UTC, Hefferman wrote: Give a template type when crating it new BubbleSort!(string) for example Is it possible to create this using "typeof"? E. g. "BubbleSort b = new BubbleSort!(typeof(arr));" Compilation fails with that line
Re: Classes and templates
On Monday, 31 October 2016 at 19:24:46 UTC, Hefferman wrote: Whenever I try to compile this, it throws an error "class sorting.BubbleSort(T) is used as a type". How do I get a workaround? Give a template type when crating it new BubbleSort!(string) for example
Classes and templates
Hello, I've been trying to implement a class for sorting which accepts arrays which "different" data types. Hard to describe, here's my example (filename sorting.d): [code] import std.random; void main() { immutable uint N = 10_000; double[] arr = new double[](N); for (uint k = 0; k < N; k++) arr[k] = uniform(0, N); BubbleSort b = new BubbleSort(); b.Sort(arr); } public class BubbleSort(T) { private T[] a; private uint n; public void Sort(T)(T[] a) { this.a = a; n = a.length; bubblesort(); } private void bubblesort() { bool sorted; do { sorted = true; for (uint k = 0; k < n; k++) { if (a[k] > a[k+1]) { T tmp = a[k]; a[k] = a[k+1]; a[k+1] = tmp; sorted = false; } } n--; } while (!sorted); } } [/code] Whenever I try to compile this, it throws an error "class sorting.BubbleSort(T) is used as a type". How do I get a workaround?