Thread overview
Proper way to accept either static or dynamic array as a parameter
Sep 12, 2021
Alex Bryan
Sep 12, 2021
H. S. Teoh
Sep 12, 2021
Alex Bryan
Sep 12, 2021
jfondren
Sep 12, 2021
Alex Bryan
September 12, 2021

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!

September 11, 2021
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
September 12, 2021

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?

September 12, 2021

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?

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.

September 12, 2021

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?

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