> 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