Thread overview
uint[3] not equivalent to void[12]?
Feb 09, 2018
Ralph Doncaster
Feb 09, 2018
Mike Parker
Feb 09, 2018
Mike Parker
Feb 09, 2018
Ralph Doncaster
Feb 09, 2018
Nicholas Wilson
Feb 09, 2018
Ralph Doncaster
Feb 09, 2018
H. S. Teoh
February 09, 2018
This seems odd to me.  Is there a way I can make a function that takes an array of any type but only of a specific size in bytes?

void.d(8): Error: function void.foo (void[12] arr) is not callable using argument types (uint[3])
Failed: ["/usr/bin/dmd", "-v", "-o-", "void.d", "-I."]
void foo(void [12] arr)
{
}

void main()
{
    uint[3] arr;
    foo(arr);
}

February 09, 2018
On Friday, 9 February 2018 at 15:05:33 UTC, Ralph Doncaster wrote:
> This seems odd to me.  Is there a way I can make a function that takes an array of any type but only of a specific size in bytes?
>
> void.d(8): Error: function void.foo (void[12] arr) is not callable using argument types (uint[3])
> Failed: ["/usr/bin/dmd", "-v", "-o-", "void.d", "-I."]
> void foo(void [12] arr)
> {
> }
>
> void main()
> {
>     uint[3] arr;
>     foo(arr);
> }

void has no size, so what does it mean to have 12 of them?

Here are a couple of options, depending on what you need.

====
import std.stdio;

enum numBytes = 12;
void foo(T, size_t N)(T[N] arr)
    if((N * T.sizeof) == numBytes)
{
	writeln(arr);
}

void bar(ubyte[12] arr)
{
    writeln(arr);
}

void main()
{
    uint[3] arr = [20, 10, 1];
    foo(arr);
    bar(cast(ubyte[12])arr);
}
===

Output:
[20, 10, 1]
[20, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0]
February 09, 2018
On Friday, 9 February 2018 at 15:24:27 UTC, Mike Parker wrote:

>
> ====
> import std.stdio;
>
> enum numBytes = 12;
> void foo(T, size_t N)(T[N] arr)
>     if((N * T.sizeof) == numBytes)
> {
> 	writeln(arr);
> }
>
> void bar(ubyte[12] arr)
> {
>     writeln(arr);
> }

Also, it's worth mentioning in case you aren't aware that this can be expensive, depending on the size of the array. Static arrays are passed by value. You may want to make the arr parameters ref or, if you want to protect the contents, const ref:

void foo(T, size_t N)(ref const(T)[N] arr)
February 09, 2018
On Friday, 9 February 2018 at 15:24:27 UTC, Mike Parker wrote:
> On Friday, 9 February 2018 at 15:05:33 UTC, Ralph Doncaster wrote:
>> This seems odd to me.  Is there a way I can make a function that takes an array of any type but only of a specific size in bytes?
>>
>> void.d(8): Error: function void.foo (void[12] arr) is not callable using argument types (uint[3])
>> Failed: ["/usr/bin/dmd", "-v", "-o-", "void.d", "-I."]
>> void foo(void [12] arr)
>> {
>> }
>>
>> void main()
>> {
>>     uint[3] arr;
>>     foo(arr);
>> }
>
> void has no size, so what does it mean to have 12 of them?

according to the docs and my testing, the size of a void array element is 1, so the following code prints 12:
import std.stdio;

void foo(void [] arr)
{
    writeln("length: " arr.length);
}

void main()
{
    uint[3] arr;
    foo(arr);
}

I thought about using templates, but I was looking for a simple way of making a function that takes an array of 12 bytes, whether it is uint[3], ubyte[12], or ushort[6].

February 09, 2018
On Friday, 9 February 2018 at 15:50:24 UTC, Ralph Doncaster wrote:
> On Friday, 9 February 2018 at 15:24:27 UTC, Mike Parker wrote:
>> On Friday, 9 February 2018 at 15:05:33 UTC, Ralph Doncaster wrote:
>>> This seems odd to me.  Is there a way I can make a function that takes an array of any type but only of a specific size in bytes?
>>>
>>> void.d(8): Error: function void.foo (void[12] arr) is not callable using argument types (uint[3])
>>> Failed: ["/usr/bin/dmd", "-v", "-o-", "void.d", "-I."]
>>> void foo(void [12] arr)
>>> {
>>> }
>>>
>>> void main()
>>> {
>>>     uint[3] arr;
>>>     foo(arr);
>>> }
>>
>> void has no size, so what does it mean to have 12 of them?
>
> according to the docs and my testing, the size of a void array element is 1,

Correct.

> so the following code prints 12:
> import std.stdio;
>
> void foo(void [] arr)
> {
>     writeln("length: " arr.length);
> }
>
> void main()
> {
>     uint[3] arr;
>     foo(arr);
> }
>
> I thought about using templates, but I was looking for a simple way of making a function that takes an array of 12 bytes, whether it is uint[3], ubyte[12], or ushort[6].

uint[3] and void[12] have the same size but are different types so the compiler will reject it.
you can reinterpret cast them(i.e. *cast(void[12])(&arr) ), but this is a rather blunt tool. Is it safe in the case that the types size is at least 12 but not safe in general.

>Is there a way I can make a function that takes an array of any type but only of a specific size in bytes?

With a template that constrains the types size:

void foo(T)(T t) if (T.sizeof == 12)
{
    //...
}

alternately reject incorrect values at runtime

void foo(ubyte[] t)
in
{
    assert(t.length == 12);
}
do
{
    //...
}

February 09, 2018
On Friday, 9 February 2018 at 16:28:50 UTC, Nicholas Wilson wrote:
> On Friday, 9 February 2018 at 15:50:24 UTC, Ralph Doncaster wrote:
>>Is there a way I can make a function that takes an array of any type but only of a specific size in bytes?
>
> With a template that constrains the types size:
>
> void foo(T)(T t) if (T.sizeof == 12)
> {
>     //...
> }
>
> alternately reject incorrect values at runtime
>
> void foo(ubyte[] t)
> in
> {
>     assert(t.length == 12);
> }
> do
> {
>     //...
> }

Thanks.  That's what I thought.  If I stick with using D, I'll probably go with the runtime check.

February 09, 2018
On Fri, Feb 09, 2018 at 03:05:33PM +0000, Ralph Doncaster via Digitalmars-d-learn wrote:
> This seems odd to me.  Is there a way I can make a function that takes an array of any type but only of a specific size in bytes?
> 
> void.d(8): Error: function void.foo (void[12] arr) is not callable
> using argument types (uint[3])
> Failed: ["/usr/bin/dmd", "-v", "-o-", "void.d", "-I."]
> void foo(void [12] arr)
> {
> }
> 
> void main()
> {
>     uint[3] arr;
>     foo(arr);
> }

You probably didn't mean to pass a static array, because those are passed by value and may entail unnecessary copying. (Though in this case, if you're only expecting 12 bytes, that's not that big of a difference.)

But in any case, probably something like this would do:

	void foo(void[] arr)
	in { assert(arr.length == 12); }
	do {
		...
	}


T

-- 
If creativity is stifled by rigid discipline, then it is not true creativity.