www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - overloading functions against function templates

reply Walter Bright <newshound1 digitalmars.com> writes:
Currently, that can't be done. But it would be good to get it in for D2. 
The question is, what rule to use?

I suggest that:

1. if any functions match, then overload functions the usual way

2. if no functions match, then overload the function templates the usual way

Or reverse the priority of the two.

What do you think?
Jul 30 2009
next sibling parent reply grauzone <none example.net> writes:
Walter Bright wrote:
 Currently, that can't be done. But it would be good to get it in for D2. 

What for?
Jul 30 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
grauzone:
What for?<

Even if for every person that may ask for such feature, there are probably 30 persons that may ask for the "stacktrace hack" built-in in DMD, I presume such overload of functions against function templates is more fun to implement :-) DMD is probably fun-driven too, not just community-needs-driven :-) Bye, bearophile
Jul 30 2009
parent Trass3r <mrmocool gmx.de> writes:
bearophile schrieb:
 Even if for every person that may ask for such feature, there are probably 30
persons that may ask for the "stacktrace hack" built-in in DMD

That's true :)
Jul 30 2009
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter Bright:
Currently, that can't be done. But it would be good to get it in for D2.<

I think someone has already asked for this feature, time ago :-)
 The question is, what rule to use?
 I suggest that:
 1. if any functions match, then overload functions the usual way
 2. if no functions match, then overload the function templates the usual way
 Or reverse the priority of the two.
 What do you think?

I'm ignorant, so here is an example to see if I have understood what you mean: import std.stdio: writeln; double foo(int x) { return x * 2; } double foo(float x) { return x * 3; } double foo(T)(T x) { return x * 4; } double foo(T : double)(T x) { return x * 5; } void main() { writeln(foo(10)); // prints: writeln(foo(10.5)); // prints: writeln(foo(10.5f)); // prints: writeln(foo(10U)); // prints: } What's the output? I think functions have to be used first, when possible, to reduce "template bloat". Bye, bearophile
Jul 30 2009
next sibling parent ponce <aliloko gmail.com> writes:
How would compete template specialization and matching functions ?

like :

double foo(double x) { return x * 2; }
double foo(T)(T x) { return x * 3; }
double foo(T : double)(T x) { return x * 4; }

writeln(foo(4.0));
Jul 30 2009
prev sibling parent Michal Minich <michal.minich gmail.com> writes:
bearophile wrote:

 import std.stdio: writeln;
 double foo(int x) { return x * 2; }
 double foo(float x) { return x * 3; } double foo(T)(T x) { return x * 4;
 }
 double foo(T : double)(T x) { return x * 5; } void main() {
     writeln(foo(10));    // prints:
     writeln(foo(10.5));  // prints:
     writeln(foo(10.5f)); // prints:
     writeln(foo(10U));   // prints:
 }
 
 What's the output?
 I think functions have to be used first, when possible, to reduce
 "template bloat".

I'm not sure by choosing function first, code size will be lower. I'm not sure how dmd works, but I think by choosing template foo, code will be generated only once for both Point and size classes. (correct me if I'm wrong) Thus I agree the functions should be chosen first, because functions are more specific. class Point { int x, y; } class Size { int width, height; } void foo (Point P) { ... } void foo (Size s) { ... } void foo (T) (T t) { ... } void main () { foo (new Point()); foo (new Point()); }
Jul 31 2009
prev sibling next sibling parent BCS <ao pathlink.com> writes:
Reply to Walter,

 Currently, that can't be done. But it would be good to get it in for
 D2. The question is, what rule to use?
 
 I suggest that:
 
 1. if any functions match, then overload functions the usual way
 
 2. if no functions match, then overload the function templates the
 usual way
 
 Or reverse the priority of the two.
 
 What do you think?
 

That sounds good. One other option would be to go with: 1. if any function matches exactly, then use it 2. if no function match exactly, then overload the function templates the usual way. 3. take the resulting function from step #2 and add it into the non-template overload list and process it the usual way.
Jul 30 2009
prev sibling next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
My intuition would be that functions are more concrete than templates, and 
thus will be checked first.

Will implicit conversions match the same way as exact type matches?
Jul 30 2009
prev sibling next sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Walter Bright wrote:
 Currently, that can't be done. But it would be good to get it in for D2. 
 The question is, what rule to use?

Yay! I've been waiting for this! :)
 I suggest that:
 
 1. if any functions match, then overload functions the usual way
 
 2. if no functions match, then overload the function templates the usual 
 way
 
 Or reverse the priority of the two.
 
 What do you think?

I think: 1: Look for exact function matches 2: Look for exact function template matches 3: Look for compatible function matches 4: Look for compatible function template matches If you are going to allow ordinary and templated functions to overload against each other, there is a problem with IFTI that I think will become more visible. It's something I run into all the time: T sum(T)(T a, T b) { return a + b; } real x = 2.0; real y = sum(1.0, x); The above doesn't compile, because 1.0 is a double literal, while x is a real. However, if this was an ordinary function with T->real, it would be valid code. I think it should also work with templates. Granted, I don't know how the matching procedure works now, but for this case I picture it could be something like this: Given: T sum(T)(T a, T b, T c) { return a + b + c; } sum(x, y, z); then do the following: 1: Try T = typeof(x). If it works, use it. 2: Try T = typeof(y). If it works, use it. 3: Try T = typeof(z). If it works, use it. 4: Give template matching error. -Lars
Jul 31 2009
parent BCS <none anon.com> writes:
Hello Lars,

 If you are going to allow ordinary and templated functions to overload
 against each other, there is a problem with IFTI that I think will
 become more visible. It's something I run into all the time:
 
 T sum(T)(T a, T b) { return a + b; }
 
 real x = 2.0;
 
 real y = sum(1.0, x);
 
 The above doesn't compile, because 1.0 is a double literal, while x is
 a real. However, if this was an ordinary function with T->real, it
 would be valid code. I think it should also work with templates.

Ditto on this
 
 Granted, I don't know how the matching procedure works now, but for
 this case I picture it could be something like this:
 
 Given:
 
 T sum(T)(T a, T b, T c) { return a + b + c; }
 
 sum(x, y, z);
 
 then do the following:
 1: Try T = typeof(x). If it works, use it.
 2: Try T = typeof(y). If it works, use it.
 3: Try T = typeof(z). If it works, use it.
 4: Give template matching error.

Something about that rules set doesn't seem rigorous enough. I'm not sure what.
Jul 31 2009
prev sibling next sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Thu, 30 Jul 2009 14:09:21 -0700, Walter Bright wrote:

 Currently, that can't be done. But it would be good to get it in for D2. 
 The question is, what rule to use?
 
 I suggest that:
 
 1. if any functions match, then overload functions the usual way
 
 2. if no functions match, then overload the function templates the usual way
 
 Or reverse the priority of the two.
 
 What do you think?

I think regular functions should go first. Let's take 4 functions for example: void foo(int); void foo(long); void foo(T)(T); void foo(T : int)(T); and call foo(5); If regular functions go first, we can order ours by match quality: void foo(int); <= best void foo(long); void foo(T : int)(T); void foo(T)(T); <= worst That's OK, the worst match is the least specialized template. But if we consider templates first: void foo(T : int)(T); <= best void foo(T)(T); void foo(int); void foo(long); <= worst What I strongly dislike about this is that a generic, non-specialized foo(T)(T) effectively hides any non-templated and obviously more specialized regular functions. I think this simply won't work.
Jul 31 2009
prev sibling parent Jason House <jason.james.house gmail.com> writes:
Walter Bright Wrote:

 Currently, that can't be done. But it would be good to get it in for D2. 
 The question is, what rule to use?

My vote would be to use partial ordering [1] for consistency. I'm just not sure what that would mean in this situation :( [1] http://dobbscodetalk.com/index.php?option=com_myblog&show=Function-Overloading-With-Partial-Ordering.html&Itemid=29
Jul 31 2009