www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Operator overloading problem

reply Blonder <andreas schniertshauer.de> writes:
Hello,

can someone help me with this?

struct Group {
    int i1;
    Group opBinary(string op)(int x) {
        // do somehting
        return this;
    }
    Group opBinary(string op)(Group g) {
        // do something
        return this;
    }
}


Group g, h;
g.i1 = 1;

h = g+g;
Aug 06 2010
next sibling parent reply Jonathan M Davis <jmdavisprog gmail.com> writes:
On Friday, August 06, 2010 12:30:38 Blonder wrote:
 Hello,
 
 can someone help me with this?
 
 struct Group {
     int i1;
     Group opBinary(string op)(int x) {
         // do somehting
         return this;
     }
     Group opBinary(string op)(Group g) {
         // do something
         return this;
     }
 }
 
 
 Group g, h;
 g.i1 = 1;
 
 h = g+g;

I think that you need to be more specific with your question. What exactly do you want help with? Are you trying to figure out how operator overloading works? Are you trying to figure out how it would be specifically done in this case? What exactly are you looking for help with? - Jonathan M Davis
Aug 06 2010
parent reply Blonder <andreas schniertshauer.de> writes:
Hello, I am trying to understand how operator overloading works with D. I am a
C++
programmer and I am reading the book of Andrei Alexandrescu and try to
understand
D and it's language features.

My Group example don't compile, the error is:
Error: template instance opBinary!("+") matches more than one template
declaration, ...

I know that it matches more than one, that was my intention, because I want to
be
able to write also

h = g+2 for example.

Is this possible in D?
Can you help me?
Thanks,
Andreas.
Aug 06 2010
parent reply div0 <div0 sourceforge.net> writes:
On 06/08/2010 21:08, Blonder wrote:
 Hello, I am trying to understand how operator overloading works with D. I am a
C++
 programmer and I am reading the book of Andrei Alexandrescu and try to
understand
 D and it's language features.

 My Group example don't compile, the error is:
 Error: template instance opBinary!("+") matches more than one template
 declaration, ...

 I know that it matches more than one, that was my intention, because I want to
be
 able to write also

 h = g+2 for example.

 Is this possible in D?
 Can you help me?
 Thanks,
 Andreas.

You need to add a second template parameter for the function arguments and add a template constrait like so: struct Group { int i1; Group opBinary(string op, U) (U x) if(op == "+" && is(U: int)) { // do somehting return this; } Group opBinary(string op, U) (U rhs) if(op == "+" && is(U: Group)) { // do something return this; } } void main() { Group g, h; g.i1 = 1; h = g+g; } Personally, I'm with you and I would expect that the compiler should example the function parameters after the template string parameter but it doesn't. It's important to note: you must use the template parameter U, you can not explitictly use the type (int/Group) like you can in C++. ie you can't do: struct Group { int i1; // DOES NOT WORK Group opBinary(string op, U) (int x) if(op == "+" && is(U: int)) { // do somehting return this; } // DOES NOT WORK Group opBinary(string op, U) (Group rhs) if(op == "+" && is(U: Group)) { // do something return this; } } -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Aug 06 2010
next sibling parent reply div0 <div0 sourceforge.net> writes:
On 06/08/2010 21:37, div0 wrote:
 You need to add a second template parameter for the function arguments
 and add a template constrait like so:

 struct Group {
     int i1;

     Group opBinary(string op, U) (U x)
     if(op == "+" && is(U: int))
     {
 	// do somehting
 	return this;
     }

     Group opBinary(string op, U) (U rhs)
     if(op == "+" && is(U: Group))
     {
 	// do something
 	return this;
     }
 }

And if you are old school C++ and don't like these new fangled template constraints you can use specialisation as well: struct Group { int i1; Group opBinary(string op : "+", U: int) (U x) { // do somehting return this; } Group opBinary(string op : "+", U: Group) (U rhs) { // do something return this; } } -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Aug 06 2010
parent reply Blonder <andreas schniertshauer.de> writes:
Is there a difference (performance) or something else between the two solutions?
Aug 07 2010
parent div0 <div0 sourceforge.net> writes:
On 07/08/2010 16:25, Blonder wrote:
 Is there a difference (performance) or something else between the two
solutions?

I doubt it, templates are applied at compile time in the front end of the compiler so the generated code should be the same. The if style syntax allows much more comprehensive restrictions to be placed on the template, but if it's a simple restriction the specialisation looks a bit neater. (well I think so) -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Aug 07 2010
prev sibling parent reply Blonder <andreas schniertshauer.de> writes:
Hello,

this seems to work, but if I add the following

	double opBinary(string op, U) (U rhs)
	{
		static if(op == "^" && is(U: Group))
		{
			// do something
			return 42;
		}
	}

because I want to write the following: double d = g^h;
I have the same problem again.

This syntax isn't very intuitive.
Aug 06 2010
parent reply div0 <div0 sourceforge.net> writes:
On 06/08/2010 22:24, Blonder wrote:
 Hello,

 this seems to work, but if I add the following

 	double opBinary(string op, U) (U rhs)
 	{
 		static if(op == "^"&&  is(U: Group))
 		{
 			// do something
 			return 42;
 		}
 	}

 because I want to write the following: double d = g^h;
 I have the same problem again.

You should only use the static if on the 2nd template parameter. You want: class Group { void opBinrary(string op, U)(U rhs) if(op == "^") { } void opBinrary(string op, U)(U rhs) if(op == "+") { } void opBinrary(string op, U)(U rhs) if(op == "-") { } void opBinrary(string op, U)(U rhs) if(op == "*") { } } Note that the 'if' is a template constraint is and part of the template signature; this is what stops you getting multiple matches when trying to determine which template to use. You can only use the static if inside the function if all the types U are similar, otherwise you'll get conversion problems with return values and such.
 This syntax isn't very intuitive.

No programming language is intuitive; they all take time to learn. D is a big win over C++ though and well worth sticking with. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Aug 06 2010
parent Blonder <andreas schniertshauer.de> writes:
Thanks, that is the solution.

 No programming language is intuitive; they all take time to learn.
 D is a big win over C++ though and well worth sticking with.

Yes, you are right, it takes time to learn. Philippe Sigaud Thanks also.
Aug 06 2010
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--001636c5b05f73f1e7048d2e2d2f
Content-Type: text/plain; charset=ISO-8859-1

On Fri, Aug 6, 2010 at 22:37, div0 <div0 sourceforge.net> wrote:

 Personally, I'm with you and I would expect that the compiler should
 example the function parameters after the template string parameter but it
 doesn't.

Yes :o( You need to add a second template parameter for the function arguments and add a template constrait like so:
 struct Group {
    int i1;

    Group opBinary(string op, U) (U x)
                if(op == "+" && is(U: int))
        {
        // do somehting
        return this;
    }

        Group opBinary(string op, U) (U rhs)
                if(op == "+" && is(U: Group))
        {
        // do something
        return this;
    }
 }

Group opBinary(string op, U)(U u) if (op == "+") { common code for all U's; static if (some test on U) some code; else other code; } Maybe some code is common between the Group case and the int case. I'm not sure it's more readable this way... Philippe --001636c5b05f73f1e7048d2e2d2f Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Fri, Aug 6, 2010 at 22:37, div0 <span dir=3D"= ltr">&lt;<a href=3D"mailto:div0 sourceforge.net">div0 sourceforge.net</a>&g= t;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0pt = 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex= ;"> <div><div class=3D"h5"> Personally, I&#39;m with you and I would expect that the compiler should=20 example the function parameters after the template string parameter but=20 it doesn&#39;t.</div></div></blockquote><div><br>Yes :o(<br>You need to add= a second template parameter for the function arguments and add a template = constrait like so:<br><br></div><blockquote class=3D"gmail_quote" style=3D"= margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); paddi= ng-left: 1ex;"> <br> struct Group {<br> =A0 =A0int i1;<br> <br> =A0 =A0Group opBinary(string op, U) (U x)<br> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if(op =3D=3D &quot;+&quot; &amp;&amp; is(U:= int))<br> =A0 =A0 =A0 =A0{<br> =A0 =A0 =A0 =A0// do somehting<br> =A0 =A0 =A0 =A0return this;<br> =A0 =A0}<br> <br> =A0 =A0 =A0 =A0Group opBinary(string op, U) (U rhs)<br> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if(op =3D=3D &quot;+&quot; &amp;&amp; is(U:= Group))<br> =A0 =A0 =A0 =A0{<br> =A0 =A0 =A0 =A0// do something<br> =A0 =A0 =A0 =A0return this;<br> =A0 =A0}<br> }<br><br></blockquote><div><br>In some cases, you might factor things a bit= :<br><br>Group opBinary(string op, U)(U u) if (op =3D=3D &quot;+&quot;)<br>= {<br>=A0=A0 common code for all U&#39;s;<br><br>=A0=A0=A0 static if (some t= est on U)<br> =A0 =A0 =A0 some code;<br>=A0=A0 else<br>=A0 =A0=A0 other code;<br>}<br><br=
Maybe=A0 some code is common between the Group case and the int case. I&#3=

v></div> --001636c5b05f73f1e7048d2e2d2f--
Aug 06 2010