resolving template instantiations
Christian Kamm
kamm-incasoftware at removethis.de
Tue Jun 30 09:12:11 PDT 2009
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.
More information about the Digitalmars-d
mailing list