www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Templated struct operator overloading

reply Peter Alexander <peter.alexander.au gmail.com> writes:
Is this a bug, or a limitation of how operator overloads handle generic 
operands?

   struct Vec(int N) {}

   struct Mat(int M, int N)
   {
       Vec!(M) opBinary(string op)(in Vec!(N) rhs)
       {
           return Vec!(M)();
       }
   }

   void main()
   {
       Vec!(3) v;
       Mat!(3, 3) m;

       Vec!(3) x = m * v; // Error: incompatible types for m * v
       Vec!(3) y = m.opBinary("*")(v); // Works
   }

Note that if you change the operator signature to:

   Vec!(3) opBinary(string op)(in Vec!(3) rhs)

then the first statement also compiles, but of course this makes the 
program incorrect.

Is this a bug or a language limitation?
Aug 06 2010
parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--000325558c9ed10932048d2d8c44
Content-Type: text/plain; charset=ISO-8859-1

On Fri, Aug 6, 2010 at 21:54, Peter Alexander
<peter.alexander.au gmail.com>wrote:

 Is this a bug, or a limitation of how operator overloads handle generic
 operands?

  struct Vec(int N) {}

  struct Mat(int M, int N)
  {
      Vec!(M) opBinary(string op)(in Vec!(N) rhs)
      {
          return Vec!(M)();
      }
  }

  void main()
  {
      Vec!(3) v;
      Mat!(3, 3) m;

      Vec!(3) x = m * v; // Error: incompatible types for m * v
      Vec!(3) y = m.opBinary("*")(v); // Works
  }

 Note that if you change the operator signature to:

  Vec!(3) opBinary(string op)(in Vec!(3) rhs)

 then the first statement also compiles, but of course this makes the
 program incorrect.

 Is this a bug or a language limitation?

I don't know how to classify it. You can help the compiler by defining aliases to types: struct Mat(int M, int N) { alias Vec!N ColumnType; alias Vec!M RowType; RowType opBinary(string op)(ColumnType rhs) { return RowType(); } } And then it works! A nice side-effect is that, given an M, you now have M.ColumType and M.RowType exposed, to do what you want. Maybe another possibility is to use templates constraints? Philippe --000325558c9ed10932048d2d8c44 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Fri, Aug 6, 2010 at 21:54, Peter Alexander <s= pan dir=3D"ltr">&lt;<a href=3D"http://peter.alexander.au">peter.alexander.a= u</a> <a href=3D"http://gmail.com">gmail.com</a>&gt;</span> wrote:<br><bloc= kquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-lef= t: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> Is this a bug, or a limitation of how operator overloads handle generic ope= rands?<br> <br> =A0struct Vec(int N) {}<br> <br> =A0struct Mat(int M, int N)<br> =A0{<br> =A0 =A0 =A0Vec!(M) opBinary(string op)(in Vec!(N) rhs)<br> =A0 =A0 =A0{<br> =A0 =A0 =A0 =A0 =A0return Vec!(M)();<br> =A0 =A0 =A0}<br> =A0}<br> <br> =A0void main()<br> =A0{<br> =A0 =A0 =A0Vec!(3) v;<br> =A0 =A0 =A0Mat!(3, 3) m;<br> <br> =A0 =A0 =A0Vec!(3) x =3D m * v; // Error: incompatible types for m * v<br> =A0 =A0 =A0Vec!(3) y =3D m.opBinary(&quot;*&quot;)(v); // Works<br> =A0}<br> <br> Note that if you change the operator signature to:<br> <br> =A0Vec!(3) opBinary(string op)(in Vec!(3) rhs)<br> <br> then the first statement also compiles, but of course this makes the progra= m incorrect.<br> <br> Is this a bug or a language limitation?<br> </blockquote></div><br>I don&#39;t know how to classify it. You can help th= e compiler by defining aliases to types:<br><br>struct Mat(int M, int N)<br=
=A0{<br>=A0=A0=A0=A0 alias Vec!N ColumnType;<br>=A0=A0=A0=A0 alias Vec!M R=

=A0=A0=A0=A0 RowType opBinary(string op)(ColumnType rhs)<br>=A0=A0=A0=A0 {<= br>=A0=A0=A0=A0=A0=A0=A0=A0 return RowType();<br>=A0=A0=A0=A0 }<br>=A0}<br>= <br>And then it works!<br>A nice side-effect is that, given an M, you now h= ave M.ColumType and M.RowType exposed, to do what you want.<br> <br>Maybe another possibility is to use templates constraints?<br><br>Phili= ppe<br><br><br> --000325558c9ed10932048d2d8c44--
Aug 06 2010