www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - template type deduction of static 2d arrays

reply "uri" <gmail gmail.com> writes:
Hi All,

I was wondering why in the code below f1() works but f2 template 
version called in the same manner does not. Is there a good 
reason from a language/compiler perspective?

Thanks.
uri


---
auto f1(int[2][2] m)
{
     return m[0][0]*m[1][1]-m[0][1]*m[1][0];
}
auto f2(T)(T[2][2] m)
{
     return m[0][0]*m[1][1]-m[0][1]*m[1][0];
}

void main()
{
     auto res = f1( [[1,2],[3,4]]); // works
     assert(res == -2);

     res = f2([[1,2],[3,4]]); // deos not work
}

Calling f2() as done above gives the following error:

Error: cannot deduce function from argument types !()(int[][]), 
candidates are:
f2(T)(T[2][2] m)
Oct 24 2014
next sibling parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 25/10/2014 11:32 a.m., uri wrote:
 Hi All,

 I was wondering why in the code below f1() works but f2 template version
 called in the same manner does not. Is there a good reason from a
 language/compiler perspective?

 Thanks.
 uri


 ---
 auto f1(int[2][2] m)
 {
      return m[0][0]*m[1][1]-m[0][1]*m[1][0];
 }
 auto f2(T)(T[2][2] m)
 {
      return m[0][0]*m[1][1]-m[0][1]*m[1][0];
 }

 void main()
 {
      auto res = f1( [[1,2],[3,4]]); // works
      assert(res == -2);

      res = f2([[1,2],[3,4]]); // deos not work
 }

 Calling f2() as done above gives the following error:

 Error: cannot deduce function from argument types !()(int[][]),
 candidates are:
 f2(T)(T[2][2] m)
res = f2(cast(int[2][2])[[1,2],[3,4]]); Should work. I believe this the old nefarious type deduction problem for literal arrays. Basically the array literals are not literally literals but instead normal arrays.
Oct 24 2014
prev sibling next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Fri, 24 Oct 2014 22:32:57 +0000
uri via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

D doesn't try to convert types on template argument deduction. what you
really get from '[[1,2],[3,4]]' is (int[][]), not (int[2][2]). note
that static arrays are not the same thing as dynamic arrays. for 'f1'
compiler doing this behind the curtains: 'cast(int[2][2])[[1,2],[3,4]]'.
but for 'f2' compiler can't do this, it must use the type that was
given to it. so it tries template with 'int[][]' and fails.

you can either change your template to `auto f2(T)(T[][] m)` (so it
accepts dynamic arrays', or explicitly cast your array literal:
`res =3D f2(cast(int[2][2])[[1,2],[3,4]]);`.
Oct 24 2014
prev sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Fri, 24 Oct 2014 22:32:57 +0000
uri via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

 Hi All,
=20
 I was wondering why in the code below f1() works but f2 template=20
 version called in the same manner does not. Is there a good=20
 reason from a language/compiler perspective?
=20
 Thanks.
 uri
=20
=20
 ---
 auto f1(int[2][2] m)
 {
      return m[0][0]*m[1][1]-m[0][1]*m[1][0];
 }
 auto f2(T)(T[2][2] m)
 {
      return m[0][0]*m[1][1]-m[0][1]*m[1][0];
 }
=20
 void main()
 {
      auto res =3D f1( [[1,2],[3,4]]); // works
      assert(res =3D=3D -2);
=20
      res =3D f2([[1,2],[3,4]]); // deos not work
 }
=20
 Calling f2() as done above gives the following error:
=20
 Error: cannot deduce function from argument types !()(int[][]),=20
 candidates are:
 f2(T)(T[2][2] m)
by the way, this will work too: int[2][2] v =3D [[1,2],[3,4]]; res =3D f2(v); 'cause 'v' has correct type, and initializing 'v' does 'magic casting'.
Oct 24 2014
parent reply "uri" <gmail gmail.com> writes:
On Friday, 24 October 2014 at 23:20:02 UTC, ketmar via 
Digitalmars-d-learn wrote:
 On Fri, 24 Oct 2014 22:32:57 +0000
 uri via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> 
 wrote:

 Hi All,
 
 I was wondering why in the code below f1() works but f2 
 template version called in the same manner does not. Is there 
 a good reason from a language/compiler perspective?
 
 Thanks.
 uri
 
 
 ---
 auto f1(int[2][2] m)
 {
      return m[0][0]*m[1][1]-m[0][1]*m[1][0];
 }
 auto f2(T)(T[2][2] m)
 {
      return m[0][0]*m[1][1]-m[0][1]*m[1][0];
 }
 
 void main()
 {
      auto res = f1( [[1,2],[3,4]]); // works
      assert(res == -2);
 
      res = f2([[1,2],[3,4]]); // deos not work
 }
 
 Calling f2() as done above gives the following error:
 
 Error: cannot deduce function from argument types 
 !()(int[][]), candidates are:
 f2(T)(T[2][2] m)
by the way, this will work too: int[2][2] v = [[1,2],[3,4]]; res = f2(v); 'cause 'v' has correct type, and initializing 'v' does 'magic casting'.
Thanks for replying. I think it should work because there's no ambiguity. I now have to uglify my code and make it ! safe or create a temporary. I also noticed this when trying things out: auto f2(T)(int[2][2] m) // Same error as above auto f2()(int[2][2] m) // Works as per non-template function On a related note, does the D spec guarantee the following will be rectangular in memory? auto a = [ [1,2],[3,4] ]; Cheers, uri
Oct 24 2014
next sibling parent "uri" <gmail gmail.com> writes:
On Friday, 24 October 2014 at 23:46:28 UTC, uri wrote:

 On a related note, does the D spec guarantee the following will 
 be rectangular in memory?

 auto a = [ [1,2],[3,4] ];


 Cheers,
 uri
I just checked the docs and auto a = [ [1,2],[3,4] ] will be an an array of pointers. So this cannot work (unless the compiler truly is magical :) auto a = [ [1,2],[3,4] ]; cast(int[2][2])(a); but this should work: enum a = [ [1,2],[3,4] ]; cast(int[2][2])(a); (all untested) Thanks, uri
Oct 24 2014
prev sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Fri, 24 Oct 2014 23:46:27 +0000
uri via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

 On a related note, does the D spec guarantee the following will=20
 be rectangular in memory?
=20
 auto a =3D [ [1,2],[3,4] ];
ah, no, it's not. this is array of arrays, i.e. 'int[][]'. only static arrays are guaranteed to be placed as one block of data. this will: int[2][2] a =3D [ [1,2],[3,4] ]; we have a nice PR from Kenji that allows the following declarations: int[$][$] a =3D [ [1,2],[3,4] ]; but alas, it's not in the mainline yet.
Oct 24 2014
parent reply "uri" <gmail gmail.com> writes:
On Saturday, 25 October 2014 at 00:00:54 UTC, ketmar via 
Digitalmars-d-learn >


 we have a nice PR from Kenji that allows the following 
 declarations:

   int[$][$] a = [ [1,2],[3,4] ];

 but alas, it's not in the mainline yet.
This will be cool, especially auto[$][$] also works. thanks, uri
Oct 24 2014
parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 25 Oct 2014 00:38:37 +0000
uri via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

 On Saturday, 25 October 2014 at 00:00:54 UTC, ketmar via=20
 Digitalmars-d-learn >
=20
=20
 we have a nice PR from Kenji that allows the following=20
 declarations:

   int[$][$] a =3D [ [1,2],[3,4] ];

 but alas, it's not in the mainline yet.
This will be cool, especially auto[$][$] also works.
yes, it works with that PR. i don't remember why it wasn't accepted, though. i'm using it in my DMD build since day one and observed no problems at all.
Oct 24 2014