www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - why no implicit convertion?

reply Matthias Pleh <sufu alter.com> writes:
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?
Nov 17 2010
next sibling parent reply =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Matthias Pleh <sufu alter.com> napisa=B3(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), ther= e = 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
Nov 17 2010
parent =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Dnia 17-11-2010 o 22:32:21 Tomek Sowi=F1ski <just ask.me> napisa=B3(a):

 What's best to pass such multidimensional arrays?

Good question. Maybe new char[][](4) and point the inner arrays to th=

 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 =3D b[i]; bar(helper); // ok, implicitly converted -- = Tomek
Nov 17 2010
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Nov 17 2010
parent reply Matthias Pleh <sufu alter.com> writes:
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 :)
Nov 17 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
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
Nov 17 2010
parent bearophile <bearophileHUGS lycos.com> writes:
 void bar(int N, int M)(ref int[N][M] buf) {}

But for a matrix this is often better: void bar(int N, int M)(ref int[N][M] buf) { Or even: pure void bar(int N, int M)(ref const int[N][M] buf) { Bye, bearophile
Nov 17 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Nov 17 2010
prev sibling next sibling parent div0 <div0 sourceforge.net> writes:
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
Nov 17 2010
prev sibling next sibling parent =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Dnia 17-11-2010 o 22:38:50 Jonathan M Davis <jmdavisProg gmx.com>  =

napisa=B3(a):

 There is no way (as far as I know) to
 convert that to a dynamic array of dynamic arrays. As such, the compil=

 can't
 do it implicitly or explicitly. You can probably create a dynamic arra=

 of
 dynamic arrays and assign each of the internal arrays to to each of th=

 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 a= nd = get away with no heap alloc (see my other post). -- = Tomek
Nov 17 2010
prev sibling parent spir <denis.spir gmail.com> writes:
On Wed, 17 Nov 2010 22:10:19 +0100
Matthias Pleh <sufu alter.com> wrote:

 void foo(char[] a) {}
 void bar(char[][] b) {}
=20
 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[][]
 }
=20
 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 th= e idiom string[] strings =3D 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 =E2=98=A3 spir.wikidot.com
Nov 17 2010