www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Suggestion: function template overloading

reply Kristian <kjkilpi gmail.com> writes:
It would be very nice if you could overload function templates as you ca=
n  =

in C++. Here is what I mean:

void f(T)(T val) {...}

void f(int val) {...}  //error: conflicts with the template function

It would allow you to write special cases for types that need it.


Here is an example:

int CMP__compare(T)(T left, T right) {
     return(left < right ? -1 : (left > right ? 1 : 0));
}

class Array(T) {
     typedef int function(T, T) compare_func_t;

     final int findOrdered(T obj) {
         return(findOrdered(CMP__compare, obj));
     }
     int findOrdered(compare_func_t cmp_func, T obj) {
         //use 'cmp_func' with binary search to find 'obj' from the arra=
y...
     }

     final void sort() {
         sort(CMP__compare);
     }
     void sort(compare_func_t cmp_func) {...};
}

One could ask why not to compare 'obj' directly in 'findOrdered()', i.e.=
  =

why to wrap the comparision inside a function template. This way you can=
  =

easily affect how 'obj' is searched. For example:

struct Stru {
     int a, b;
}

int CMP__compare(Stru left, Stru right) {
     if(left.a =3D=3D -1 || right.a =3D=3D -1)
         return(CMP__compare(left.b, right.b));
     else
         return(CMP__compare(left.a, right.a));
}

int CMP__compareInv(T)(T left, T right) {
     return(-CMP__compare(left, right));
}

void func() {
     int pos;
     Array!(Stru) a;
     Stru s;

     ...
     pos =3D a.findOrdered(s);
     ...
     a.sort(CMP__compareInv);
}
Aug 29 2006
parent reply Sean Kelly <sean f4.ca> writes:
Kristian wrote:
 
 It would be very nice if you could overload function templates as you 
 can in C++. Here is what I mean:
 
 void f(T)(T val) {...}
 
 void f(int val) {...}  //error: conflicts with the template function
 
 It would allow you to write special cases for types that need it.
void f(T)(T val) {} void f()(int val) {} Sean
Aug 29 2006
next sibling parent reply Kristian <kjkilpi gmail.com> writes:
On Tue, 29 Aug 2006 21:04:53 +0300, Sean Kelly <sean f4.ca> wrote:

 Kristian wrote:
  It would be very nice if you could overload function templates as yo=
u =
 can in C++. Here is what I mean:
  void f(T)(T val) {...}
  void f(int val) {...}  //error: conflicts with the template function=
  It would allow you to write special cases for types that need it.
void f(T)(T val) {} void f()(int val) {} Sean
Ah, thanks! I missed _that_ one completely... :/ But now I can't get the following to work: bool equal(T)(T l, T r) { return l =3D=3D r; } bool equal()(Foo l, Foo r) { return l.m_val =3D=3D r.m_val; } class Foo { int m_val =3D 0; } class Bar(T) { this() { m_val =3D new T; } bool eq(T obj) { return(equal(m_val, obj)); //error: matches more than one = template, equal(T) and equal() } T m_val; } void main() { Bar!(Foo) bar =3D new Bar!(Foo); Foo foo =3D new Foo; printf("%d\n", bar.eq(foo)); } It seems that 'binding' is done when 'Bar' is compiled, not when 'bar' = variable is declared.
Aug 29 2006
parent reply Sean Kelly <sean f4.ca> writes:
Kristian wrote:
 On Tue, 29 Aug 2006 21:04:53 +0300, Sean Kelly <sean f4.ca> wrote:
 
 Kristian wrote:
  It would be very nice if you could overload function templates as 
 you can in C++. Here is what I mean:
  void f(T)(T val) {...}
  void f(int val) {...}  //error: conflicts with the template function
  It would allow you to write special cases for types that need it.
void f(T)(T val) {} void f()(int val) {} Sean
Ah, thanks! I missed _that_ one completely... :/ But now I can't get the following to work: bool equal(T)(T l, T r) { return l == r; } bool equal()(Foo l, Foo r) { return l.m_val == r.m_val; } class Foo { int m_val = 0; } class Bar(T) { this() { m_val = new T; } bool eq(T obj) { return(equal(m_val, obj)); //error: matches more than one template, equal(T) and equal() } T m_val; } void main() { Bar!(Foo) bar = new Bar!(Foo); Foo foo = new Foo; printf("%d\n", bar.eq(foo)); } It seems that 'binding' is done when 'Bar' is compiled, not when 'bar' variable is declared.
In this case, it should choose equal()( Foo ... ) over equal(T)( T ...) because the Foo overload is the most specialized for the supplied parameters. Unfortunately, implicit template support in DMD is still pretty thin so you're probably running into a compiler limitation rather than a problem with the spec. Instead of: equal()( Foo l, Foo r ) try: equal( T : Foo )( Foo l, Foo r ) and see what happens. I've found that with a bit of experimentation (and perhaps some wrapper code) you can usually get ITI to work as desired, and simply remove the work-around code as DMD improves. Sean
Aug 29 2006
parent Kristian <kjkilpi gmail.com> writes:
On Tue, 29 Aug 2006 21:44:35 +0300, Sean Kelly <sean f4.ca> wrote:
 Kristian wrote:
 On Tue, 29 Aug 2006 21:04:53 +0300, Sean Kelly <sean f4.ca> wrote:

 Kristian wrote:
  It would be very nice if you could overload function templates as =
=
 you can in C++. Here is what I mean:
  void f(T)(T val) {...}
  void f(int val) {...}  //error: conflicts with the template functi=
on
  It would allow you to write special cases for types that need it.
void f(T)(T val) {} void f()(int val) {} Sean
Ah, thanks! I missed _that_ one completely... :/ But now I can't get the following to work: bool equal(T)(T l, T r) { return l =3D=3D r; } bool equal()(Foo l, Foo r) { return l.m_val =3D=3D r.m_val; } class Foo { int m_val =3D 0; } class Bar(T) { this() { m_val =3D new T; } bool eq(T obj) { return(equal(m_val, obj)); //error: matches more than one =
 template, equal(T) and equal()
     }
      T m_val;
 }
  void main() {
     Bar!(Foo) bar =3D new Bar!(Foo);
     Foo foo =3D new Foo;
      printf("%d\n", bar.eq(foo));
 }
  It seems that 'binding' is done when 'Bar' is compiled, not when 'ba=
r' =
 variable is declared.
In this case, it should choose equal()( Foo ... ) over equal(T)( T ...=
) =
 because the Foo overload is the most specialized for the supplied  =
 parameters.  Unfortunately, implicit template support in DMD is still =
=
 pretty thin so you're probably running into a compiler limitation rath=
er =
 than a problem with the spec.  Instead of:

 equal()( Foo l, Foo r )

 try:

 equal( T : Foo )( Foo l, Foo r )

 and see what happens.  I've found that with a bit of experimentation  =
 (and perhaps some wrapper code) you can usually get ITI to work as  =
 desired, and simply remove the work-around code as DMD improves.


 Sean
Ok, thanks again!
Aug 29 2006
prev sibling parent Walter Bright <newshound digitalmars.com> writes:
Sean Kelly wrote:
 Kristian wrote:
 It would be very nice if you could overload function templates as you 
 can in C++. Here is what I mean:

 void f(T)(T val) {...}

 void f(int val) {...}  //error: conflicts with the template function

 It would allow you to write special cases for types that need it.
void f(T)(T val) {} void f()(int val) {}
Or: void f(T:int)(T val) {} The trouble is that D has problems with specialization, but that's a compiler problem. C++ has complex rules regarding mixing functions and function templates with the same name. D just sidesteps the problem by disallowing that. There's no loss of functionality. I think the reason C++ did that was because the template design originally didn't allow template specialization, and when it did, it was stuck with the legacy code.
Aug 29 2006