www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - resolving template instantiations

reply Christian Kamm <kamm-incasoftware removethis.de> writes:
I started out wanting to document implicit function template instantiation 
(IFTI) and type deduction and ended up reading the DMD frontend code for 
template instantiation. There I discovered that choosing the correct 
template declaration involves more logic than the spec indicates.

The specification says that if a template instantiation has an argument list 
that fits more than one template declaration, the most specialized 
declaration is chosen. If the declarations are equally specialized or there 
is no such order, an error is raised. Determining which declaration is more 
specialized is done in a way inherited from C++: if the first declaration 
could be instantiated with any argument list that's valid for the second, 
the first is equally or less specialized than the second.

In the DMD frontend though, there's another factor that eliminates some 
candidates before the ordering criterion is applied: each template 
declaration matches the template argument list either exactly or with 
conversions (similar to function overloads). If there is at least one exact 
match, the most specialized declaration is chosen among the exact matches. 
Only if there are no exact matches is the ordering criterion used to find 
the most specialized among the matches-with-conversion.

It gets interesting when you throw in the fact that template type parameters 
without specialization will generally be considered to be match-with-
conversion only (a comment states: "so that matches with specializations are 
better"). For instance

template Foo1(T) { pragma(msg, "type"); }
template Foo1(alias T) { pragma(msg, "alias"); }
alias Foo1!(Object) f1; // alias (type is only match-with-conversions)

but

template Foo2(T : Object) { pragma(msg, "type"); }
template Foo2(alias T) { pragma(msg, "alias"); }
alias Foo2!(Object) f2; // type (both match exactly, type is more 
specialized)

(the same works with a tuple parameter instead of the alias parameter).

It's easy to see that for value parameters looking at the match quality is a 
good idea

template Bar1(int i) { pragma(msg, "int"); }
template Bar1(uint i) { pragma(msg, "uint"); }
alias Bar1!(42) b1; // int (uint only matches with conversions)

as the template instantiation would be ambiguous otherwise - neither 
declaration is more specialized than the other.

Is this intended behavior? If so, what's the rationale for checking the 
match quality for non-value parameters? Is there a case where mere template 
ordering would produce inferior results with type parameters?

If it is intended, let's document and explain it in the specification. If it 
isn't, it needs to be changed or removed before the D2 freeze makes code 
into law.
Jun 30 2009
parent reply Paul D. Anderson <paul.d.removethis.anderson comcast.andthis.net> writes:
Christian Kamm Wrote:

 
<snip/>
 If it is intended, let's document and explain it in the specification. If it 
 isn't, it needs to be changed or removed before the D2 freeze makes code 
 into law.
 
 
Have you entered this into Bugzilla to keep your list of spec issues current? Thanks for doing that, by the way. :-) Paul
Jul 01 2009
parent Christian Kamm <kamm-incasoftware removethis.de> writes:
Paul D.  Anderson wrote:
 Have you entered this into Bugzilla to keep your list of spec issues
 current?
No, I haven't yet. I was hoping to get an explanation for DMD's behavior from Walter, maybe even a discussion about the correct way to select template declarations and whether ordering by specialization is even still needed when you have template constraints. But I will make sure the issues get a Bugzilla entry if they can't be resolved directly.
Jul 02 2009