www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Overloading + on points

reply Eduardo Cavazos <wayo.cavazos gmail.com> writes:
Eduardo Cavazos <wayo.cavazos at gmail.com> wrote:

 Here's a short program which creates a type for points and overloads
'+'
 to do element wise addition as well as addition to floats, however it
 produces an error:

 ----------------------------------------------------------------------
 import std.stdio ;

 struct Pt
 {
    float x , y ;

    Pt opBinary ( string op ) ( Pt a ) if ( op == "+" )
      { return Pt ( x + a.x , y + a.y ) ; }

    Pt opBinary ( string op ) ( float a ) if ( op == "+" )
      { return Pt ( x + a , y + a ) ; }
 }

 void main () { Pt ( 1.0 , 2.0 ) + Pt ( 3.0 , 4.0 ) ; }
 ----------------------------------------------------------------------

 The error:

 pt_overload_test_a.d(15): Error: template instance opBinary!("+")
 matches more than one template declaration,
 pt_overload_test_a.d(8):opBinary(string op) if (op == "+") and
 pt_overload_test_a.d(11):opBinary(string op) if (op == "+")

 So, how should I go about this? :-)
Simen kjaeraas wrote:
 That is indeed a perplexing error. It is caused by dmd not knowing
 how to overload template functions based on both normal and template
 parameters.

 As for the solution:

 Pt opBinary( string op : "+", T : Pt )( T a ) {...}
 Pt opBinary( string op : "+", T : float )( T a ) {...}

 should work. More explicitly:

 Pt opBinary( string op, T )( T a ) if ( ( op == "+" ) && is( T == Pt ) )
 {...}
 Pt opBinary( string op, T )( T a ) if ( ( op == "+" ) && is( T == float )
 ) {...}
Is either one of those solutions preferrable? Or are they equivalent? I'd like to get these right now since there are a bunch more like this (for all the various operators and combinations). For this experiment, I was going off of the examples in TDPL and I hadn't noticed yet one which covers a case like this; perhaps for 2nd edition. ;-) Ed
Sep 02 2010
parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Eduardo Cavazos <wayo.cavazos gmail.com> wrote:

 Pt opBinary( string op : "+", T : Pt )( T a ) {...}
 Pt opBinary( string op : "+", T : float )( T a ) {...}
 Pt opBinary( string op, T )( T a ) if ( ( op == "+" ) && is( T == Pt ) )
 {...}
 Pt opBinary( string op, T )( T a ) if ( ( op == "+" ) && is( T == float  
 )
 ) {...}
Is either one of those solutions preferrable? Or are they equivalent? I'd like to get these right now since there are a bunch more like this (for all the various operators and combinations).
They are not entirely equivalent. The first two use T : float, which is a test of implicit castability, while is( T == float ) is a test for equality. IOW, the second set would barf on receiving a non-float parameter, like double or int. For some reason I messed that up. If instead I had written the tests as is( T : Pt ) and is( T : float ), they would be equivalent. string op : "+" basically means the same as the template constraint if ( op == "+" ). The latter is more flexible, as you can compare to more values than the singular value in the op : "+". -- Simen
Sep 02 2010