Questions to template overload resolution
Jonathan M Davis
jmdavisProg at gmx.com
Tue Apr 12 19:30:09 PDT 2011
> 1) T foo(T:SomeClass)(T arg){..}
> It is specified on the main page that this template will match against
> instantiations with a subclass of SomeClass. Will this also duplicate the
> code? Or will the template work similar to the function T foo(SomeClass
> arg){..}? If yes, why should normal functions and function templates
> without type params be separated at all?
Templates are used for code generation, pure and simple. They don't exist
until you instantiate them (so, for instance, if a template is horribly broken
and wouldn't compile if you tried to use it, the code will still compile as
long as the template isn't used), and every time that you instantiate a
template with a new type, it generates new code. This allows you to do some
really nice stuff with different versions of stuff for different types, as
well as stuff like eponymous templates, where you use a template to generate a
value.
The templated function
T foo(T)(T arg){...}
is really something like
template foo(T)
{
T foo(T arg) {...}
}
and the template doesn't really exist until it's instantiated, so it's very
different from a normal function, which would exist regardless of whether it
was used. And since the function could change considerably depending on the
template arguments (you can use static ifs and other templates inside the
function which could cause the instiated template function to be drastically
different depending on the template arguments, even if the template's
signature and constraints are the same).
>
> 2) Why is this an error? Obviously, the second template is a better match.
>
> What is the rationale for requiring the clumsier f(T:double,U:int)(T a,U b)
> to f()(double a,int b) to allow proper overload resolution?
>
> import std.stdio;
>
> T f(T,U)(T a,U b){
> return a;
> }
> T f()(double a,int b){
> return a;
> }
>
> void main(){
> writeln(f(1.2,1));//error
> }
> test.d(11): Error: template test.f(T,U) f(T,U) matches more than one
> template declaration, test.d(3):f(T,U) and test.d(6):f()
The second template wouldn't even work. Where does the T come from? I'm
surprised that even compiles far enough to sayt that it can't determine which
template to use. But even if you did something like
double f(U)(double a, U b)
{
return a;
}
I expect that it still wouldn't work, because it matches two separate
templates. I believe that all template overload resolutions are done via the
template arguments and template constraints and that the function arguments
don't enter into it at all. The contents of the template are only relevant
once the template has been instantiated. Remember that the definition of f is
really something like this
T f(T, U)
{
T f(T a, U b)
{
return ;
}
}
That outer template must be properly resolved before what's inside the
template is even brought into consideration.
If you want to do what you're doing, the second template would look something
more like
T f(T : double, U : int)(T a, U b)
{
return a;
}
That way, the template overload resolution can be done based on the template
parameters, not the function's parameters.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list