www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - uint[3] not equivalent to void[12]?

reply Ralph Doncaster <nerdralph github.com> writes:
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);
}
Feb 09 2018
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
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]
Feb 09 2018
next sibling parent Mike Parker <aldacron gmail.com> writes:
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)
Feb 09 2018
prev sibling parent reply Ralph Doncaster <nerdralph github.com> writes:
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].
Feb 09 2018
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
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 { //... }
Feb 09 2018
parent Ralph Doncaster <nerdralph github.com> writes:
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.
Feb 09 2018
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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.
Feb 09 2018