www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Proper way to accept either static or dynamic array as a parameter

reply Alex Bryan <abryancs gmail.com> writes:
I am having trouble discovering what the proper (or at least a 
proper) way is to write a function that can take either a static 
or dynamic array as a parameter. My current implementation 
consists of 2 overloaded functions (one takes a dynamic array, 
the other takes a static array) with 99% copy/pasted code. My 
intuition tells me this is dirty, and there's a better way to do 
this with templates, but for the life of me I just can't figure 
it out. Would someone be so kind as to please help me out?

Other than this frustration I am enjoying programming in D!
Sep 11 2021
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Sep 12, 2021 at 01:08:17AM +0000, Alex Bryan via Digitalmars-d-learn
wrote:
 I am having trouble discovering what the proper (or at least a proper)
 way is to write a function that can take either a static or dynamic
 array as a parameter. My current implementation consists of 2
 overloaded functions (one takes a dynamic array, the other takes a
 static array) with 99% copy/pasted code. My intuition tells me this is
 dirty, and there's a better way to do this with templates, but for the
 life of me I just can't figure it out.  Would someone be so kind as to
 please help me out?
[...] Just make the function take an array parameter. Static arrays will decay into a slice (though my recommendation is to explicitly slice it with the [] operator): auto myFunction(T[] data) { ... } T[10] staticArr; T[] dynArr = [ ... ]; myFunction(staticArr); // implicit slice, not recommended myFunction(staticArr[]); // explicit slice, better myFunction(dynArr); T -- Life is too short to run proprietary software. -- Bdale Garbee
Sep 11 2021
parent reply Alex Bryan <abryancs gmail.com> writes:
On Sunday, 12 September 2021 at 01:48:07 UTC, H. S. Teoh wrote:
 On Sun, Sep 12, 2021 at 01:08:17AM +0000, Alex Bryan via 
 Digitalmars-d-learn wrote:
 I am having trouble discovering what the proper (or at least a 
 proper) way is to write a function that can take either a 
 static or dynamic array as a parameter. My current 
 implementation consists of 2 overloaded functions (one takes a 
 dynamic array, the other takes a static array) with 99% 
 copy/pasted code. My intuition tells me this is dirty, and 
 there's a better way to do this with templates, but for the 
 life of me I just can't figure it out.  Would someone be so 
 kind as to please help me out?
[...] Just make the function take an array parameter. Static arrays will decay into a slice (though my recommendation is to explicitly slice it with the [] operator): auto myFunction(T[] data) { ... } T[10] staticArr; T[] dynArr = [ ... ]; myFunction(staticArr); // implicit slice, not recommended myFunction(staticArr[]); // explicit slice, better myFunction(dynArr); T
So it turns out my issue was that my function had an unnecessary ref: auto myFunction(ref T[] data) { ... } T[10] staticArr; T[] dynArr = [ ... ]; myFunction(staticArr); // does not compile myFunction(staticArr[]); // does not compile myFunction(dynArr); // compiles Since I was modifying the contents of data, I thought I needed the ref, but this is not the case. Removing the ref and the code works as you described. Let me see if I can summarize what I've learned (and ask additional questions): `T[] data` is essentially already a reference since it contains a pointer and a length and allows you to modify the contents it points to, but if I wanted to modify either the pointer or length in `T[] data` in that function (for some reason) I'd need to pass it in as a `ref`? `T[] dynArr` can be passed (by reference) to a function that takes `ref T[] data` but `T[10] data` cannot? Why not?
Sep 11 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Sunday, 12 September 2021 at 02:44:36 UTC, Alex Bryan wrote:
 `T[] dynArr` can be passed (by reference) to a function that 
 takes `ref T[] data` but `T[10] data` cannot? Why not?
```d void add1(ref int[] nums) { nums ~= 1; } unittest { int[] nums; nums.add1; nums.add1; nums.add1; assert(nums == [1, 1, 1]); } ``` the `ref` allows `add1` to extend the length of the slice passed to it, with potential reallocation. This doesn't make sense with a static array whose length can't be modified.
Sep 11 2021
parent Alex Bryan <abryancs gmail.com> writes:
On Sunday, 12 September 2021 at 02:49:48 UTC, jfondren wrote:
 On Sunday, 12 September 2021 at 02:44:36 UTC, Alex Bryan wrote:
 `T[] dynArr` can be passed (by reference) to a function that 
 takes `ref T[] data` but `T[10] data` cannot? Why not?
```d void add1(ref int[] nums) { nums ~= 1; } unittest { int[] nums; nums.add1; nums.add1; nums.add1; assert(nums == [1, 1, 1]); } ``` the `ref` allows `add1` to extend the length of the slice passed to it, with potential reallocation. This doesn't make sense with a static array whose length can't be modified.
Makes sense. Thank you
Sep 11 2021