Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 17, 2010 why no implicit convertion? | ||||
---|---|---|---|---|
| ||||
void foo(char[] a) {} void bar(char[][] b) {} int main(string[] args) { char[4] a; char[4][4] b; foo(a); // OK: implicit convertion bar(b); // Error: cannot implicitly convert // char[4u][4u] to char[][] } what is the reason for the different behaviour? What's best to pass such multidimensional arrays? |
November 17, 2010 Re: why no implicit convertion? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Pleh | Matthias Pleh <sufu@alter.com> napisał(a): > void foo(char[] a) {} > void bar(char[][] b) {} > > int main(string[] args) > { > char[4] a; > char[4][4] b; > foo(a); // OK: implicit convertion > bar(b); // Error: cannot implicitly convert > // char[4u][4u] to char[][] > } > > what is the reason for the different behaviour? I *think* it's because multi-dim static arrays are a strip of contiguous memory and no length information is held with the data, so if it was converted to a dynamic array of arrays (who do hold their lengths), there wouldn't be room for the lengths of the arrays. > What's best to pass such multidimensional arrays? Good question. Maybe new char[][](4) and point the inner arrays to the chunks of the static array? -- Tomek |
November 17, 2010 Re: why no implicit convertion? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Pleh | Matthias Pleh Wrote: > void foo(char[] a) {} > void bar(char[][] b) {} > > int main(string[] args) > { > char[4] a; > char[4][4] b; > foo(a); // OK: implicit convertion > bar(b); // Error: cannot implicitly convert > // char[4u][4u] to char[][] > } > > what is the reason for the different behaviour? char[][] is an array of dynamic arrays. A dynamic array consists of a length and a pointer A char[4][4] is a fixed array of fixed arrays. A fixed array consists of just data, the length is part of the type, and the pointer is implied. > What's best to pass such multidimensional arrays? two ways, if you want to support multiple lengths of 4-element char arrays, you could do: void bar(char[4][]) if you want to support only a 4x4 array, you can do: void bar(ref char[4][4]) If you want to pass by value, omit the ref, but this will copy all the data and you will not be able to update the original array from within the function. -Steve |
November 17, 2010 Re: why no implicit convertion? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Pleh | On Wednesday 17 November 2010 13:10:19 Matthias Pleh wrote:
> void foo(char[] a) {}
> void bar(char[][] b) {}
>
> int main(string[] args)
> {
> char[4] a;
> char[4][4] b;
> foo(a); // OK: implicit convertion
> bar(b); // Error: cannot implicitly convert
> // char[4u][4u] to char[][]
> }
>
> what is the reason for the different behaviour?
> What's best to pass such multidimensional arrays?
How would even do that conversion? char[4][4] is one solid block of memory. char[][] is an array of arrays. If you slice b - b[] - you get a char[4][] - so you have a dynamic array of static arrays. There is no way (as far as I know) to convert that to a dynamic array of dynamic arrays. As such, the compiler can't do it implicitly or explicitly. You can probably create a dynamic array of dynamic arrays and assign each of the internal arrays to to each of the internal arrays of b, but there's no direct way to do it. You're dealing with two _very_ different types here. While they may be accessed similarly, one is a statically- allocated block of memory, while the other is references to references and all on the heap. It's already buggy enough to pass a statically allocated array by reference (since the function that it's passed to doesn't know that the data is on the stack rather than the heap and could leak references to it). It would likely be very difficult to cleanly do that with multi-dimensional static arrays.
- Jonathan M Davis
|
November 17, 2010 Re: why no implicit convertion? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Pleh | On 17/11/2010 21:10, Matthias Pleh wrote: > void foo(char[] a) {} > void bar(char[][] b) {} > > int main(string[] args) > { > char[4] a; > char[4][4] b; > foo(a); // OK: implicit convertion > bar(b); // Error: cannot implicitly convert > // char[4u][4u] to char[][] > } > > what is the reason for the different behaviour? > What's best to pass such multidimensional arrays? Check the bit about rectangular arrays: http://digitalmars.com/d/2.0/arrays.html b is a static array so gets optimised to a dense array which isn't compatible with bar. well assuming the docs are up to date. Seems like a poor choice, dense arrays should be explicit. You can't pass a dense array to a func unless all but the last dimensions match: void bar(char[4][] b) { } void car(char[10][4][] c) { } void main() { char[4][4] b; bar(b); char[10][4][2] c; car(c); } -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk |
November 17, 2010 Re: why no implicit convertion? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tomek Sowiński | Dnia 17-11-2010 o 22:32:21 Tomek Sowiński <just@ask.me> napisał(a): >> What's best to pass such multidimensional arrays? > > Good question. Maybe new char[][](4) and point the inner arrays to the chunks of the static array? Correction, it can be allocated on the stack: char[4][4] b; char[][4] helper; foreach (i, ref chunk; helper) chunk = b[i]; bar(helper); // ok, implicitly converted -- Tomek |
November 17, 2010 Re: why no implicit convertion? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Am 17.11.2010 22:36, schrieb Steven Schveighoffer:
[...]
> two ways, if you want to support multiple lengths of 4-element char arrays, you could do:
>
> void bar(char[4][])
> if you want to support only a 4x4 array, you can do:
>
> void bar(ref char[4][4])
> If you want to pass by value, omit the ref, but this will copy all the data and you will not be able to update the original array from within the function.
Aah, OK!
So I solved it with:
void bar(char* buf, int width, int height)
Good old C :)
|
November 17, 2010 Re: why no implicit convertion? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | Dnia 17-11-2010 o 22:38:50 Jonathan M Davis <jmdavisProg@gmx.com> napisał(a): > There is no way (as far as I know) to > convert that to a dynamic array of dynamic arrays. As such, the compiler can't > do it implicitly or explicitly. You can probably create a dynamic array of > dynamic arrays and assign each of the internal arrays to to each of the internal > arrays of b, but there's no direct way to do it. For rectangular arrays you can create a static array of dynamic arrays and get away with no heap alloc (see my other post). -- Tomek |
November 17, 2010 Re: why no implicit convertion? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Pleh | On Wed, 17 Nov 2010 22:10:19 +0100
Matthias Pleh <sufu@alter.com> wrote:
> void foo(char[] a) {}
> void bar(char[][] b) {}
>
> int main(string[] args)
> {
> char[4] a;
> char[4][4] b;
> foo(a); // OK: implicit convertion
> bar(b); // Error: cannot implicitly convert
> // char[4u][4u] to char[][]
> }
>
> what is the reason for the different behaviour?
> What's best to pass such multidimensional arrays?
I may be wrong, but it seems (also from main's signature) you're trying to apply plain C point-of-view to a D feature (dyn array).
Also, maybe what you need is an array of strings?
Finally, to initialise a dynamic array at a given dimension, you may use the idiom
string[] strings = new string[dim];
(but this does not work for 2 dimensions, I guess)
Sorry if I'm wrong and this does not help.
Denis
-- -- -- -- -- -- --
vit esse estrany ☣
spir.wikidot.com
|
November 17, 2010 Re: why no implicit convertion? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Pleh | Matthias Pleh:
> So I solved it with:
>
> void bar(char* buf, int width, int height)
>
> Good old C :)
Most times this is not a good D solution :-(
This compiles (but it created a new instantiation of bar for each different input matrix):
void bar(int N, int M)(int[N][M] buf) {}
void main() {
int[4][4] m;
bar(m);
}
Bye,
bearophile
|
Copyright © 1999-2021 by the D Language Foundation