www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Template matching

reply xs0 <xs0 xs0.com> writes:
Hi!

The current template matching system prevents code like this:

---

template Blah(int a, alias B)
{
   // do something with Blah!(a-1, B)
}

template Blah(int a:0, alias B)
{
   // do something non-recursive
}

---

The problem is that Blah!(a-1, B) matches both templates when a==1, 
because the B parameter is not specialized in the second case. I see 
this as unnecessarily limiting.

If matches are labeled as

0 - no match
1 - match
2 - exact match

the current system would be described like this:
1) skip any template that includes a 0
2) if there's no template remaining, it's an error
3) if there's only one template remaining, it gets used
4) if there's more than one template remaining, a template must exist 
with only exact matches (just 2's), otherwise it is an error

I propose that the last rule is changed, so that if there exists a 
template with better-or-equal score for each parameter than any other 
template, it is also allowed/not an error.

So, Blah!(0, T) in the above example would produce scores (1,1) and 
(2,1), and so the second one would be chosen, because each score is 
greater or equal to scores in other templates..

OTOH, if we had

template Foo(int a, int b, alias C) ...
template Foo(int a:0, int b, alias C) ...
template Foo(int a, int b:0, alias C) ...

Foo!(0, 0, T) would produce scores

(1, 1, 1)
(2, 1, 1)
(1, 2, 1)

And so it would be an error, because no template has every element of 
its score higher or equal to corresponding elements of scores in other 
templates. Adding template Foo(int a:0, int b:0, alias C) would resolve 
that problem, because its score would be (2, 2, 1).

On a final note, it's funny that the above example works if B is not an 
alias, which I don't quite get - where's the major difference?


xs0
Mar 29 2005
next sibling parent "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 30 Mar 2005 03:47:14 +0200, xs0 <xs0 xs0.com> wrote:
 Hi!

 The current template matching system prevents code like this:

 ---

 template Blah(int a, alias B)
 {
    // do something with Blah!(a-1, B)
 }

 template Blah(int a:0, alias B)
 {
    // do something non-recursive
 }

 ---

 The problem is that Blah!(a-1, B) matches both templates when a==1,  
 because the B parameter is not specialized in the second case. I see  
 this as unnecessarily limiting.

I agree. What is the point of a specialisation if it does not have precedence over the general case? Regan
Mar 30 2005
prev sibling next sibling parent xs0 <xs0 xs0.com> writes:
Nobody else has any thoughts on this proposal?

After some more thinking, it could be used with function parameters as 
well, so one could do this:

func(int a, short b);
func(long a, short b);

void main()
{
     int i;
     func(i, 5); // currently you need to do cast(short)5
                 // w/my proposal it would match the first func()
}

Additionally, it would really make sense to handle out and inout 
parameters in a special manner, because they only work with exact 
matching anyway.. For example:

func(out int a, short b);
func(out long b, float c);

void main()
{
     long a;
     short b=3;

     func(a,b); // this should match the second func(), because
                // the first one can't ever be used with long a
}

To sum up:
- the three-level matching is kept, but done per-parameter
- when out/inout parameters are used, functions that don't exactly match 
those parameters are not even considered
- if there is no exact match, and more than one non-exact match, it is 
still an error, like now, unless one function (and not more) exactly 
matches at least all parameters, where other functions have an exact match

The same goes for templates, except it has no out/inout parameters :)

These rules are almost as simple as the current system, yet handle a lot 
of cases where it's really obvious which overload should be used, but it 
currently isn't, because not all parameters are an exact match.. There 
are still no complicated rules no-one would know/understand, because 
there are still basically only two levels of matching - exact and 
non-exact, and it can't happen that an exact match on one parameter 
would mean more or less than an exact match on some other parameter 
(which I totally agree is confusing).


xs0



xs0 wrote:
 Hi!
 
 The current template matching system prevents code like this:
 
 ---
 
 template Blah(int a, alias B)
 {
   // do something with Blah!(a-1, B)
 }
 
 template Blah(int a:0, alias B)
 {
   // do something non-recursive
 }
 
 ---
 
 The problem is that Blah!(a-1, B) matches both templates when a==1, 
 because the B parameter is not specialized in the second case. I see 
 this as unnecessarily limiting.
 
 If matches are labeled as
 
 0 - no match
 1 - match
 2 - exact match
 
 the current system would be described like this:
 1) skip any template that includes a 0
 2) if there's no template remaining, it's an error
 3) if there's only one template remaining, it gets used
 4) if there's more than one template remaining, a template must exist 
 with only exact matches (just 2's), otherwise it is an error
 
 I propose that the last rule is changed, so that if there exists a 
 template with better-or-equal score for each parameter than any other 
 template, it is also allowed/not an error.
 
 So, Blah!(0, T) in the above example would produce scores (1,1) and 
 (2,1), and so the second one would be chosen, because each score is 
 greater or equal to scores in other templates..
 
 OTOH, if we had
 
 template Foo(int a, int b, alias C) ...
 template Foo(int a:0, int b, alias C) ...
 template Foo(int a, int b:0, alias C) ...
 
 Foo!(0, 0, T) would produce scores
 
 (1, 1, 1)
 (2, 1, 1)
 (1, 2, 1)
 
 And so it would be an error, because no template has every element of 
 its score higher or equal to corresponding elements of scores in other 
 templates. Adding template Foo(int a:0, int b:0, alias C) would resolve 
 that problem, because its score would be (2, 2, 1).
 
 On a final note, it's funny that the above example works if B is not an 
 alias, which I don't quite get - where's the major difference?
 
 
 xs0

Apr 01 2005
prev sibling parent "Ben Hinkle" <ben.hinkle gmail.com> writes:
 On a final note, it's funny that the above example works if B is not an 
 alias, which I don't quite get - where's the major difference?

Maybe you are seeing a bug with alias template parameters. I agree the behavior seems like something should change. Hopefully alias can be made to act like other template parameters.
Apr 01 2005