On Thursday, 10 August 2023 at 14:34:20 UTC, Michael Galuza wrote:
> On Wednesday, 9 August 2023 at 18:28:38 UTC, sighoya wrote:
> Giving it an explicit type make it workable
Of course, but such usage of a template functions is... useless:-) I want type argument T
will be inferred.
Anyway, I wondered why compiler rewrite square!(int)(3)
as square!(int).square(3)
, but in the same time it's not so clever to eliminate !(int)
. I can only guess that type inference is impossible in this situation. I mean in ordinary cases compiler can match literal 3
and type int
directly, but what it should do in such simple case:
template square(T) {
static if (is(T)) {
T square(T t) {
return t * t;
}
}
}
Of course compiler could conclude that expression square(3)
is correct only if static if
branch was successful, so is(T) == true && T == int
(hi, Hindley–Milner :-), but such type inference require complex analysis "bottom-up", from template members to template itself, whereas we analyse template body "up-down", from template args and static if-s to members.
Of course all above is just my poor and miserable tryings to understand compiler's pranks, don't judge me.
D has template constraints that will do that for you(but I don't think it works when you explicitly use template
keyword):
import std;
T square(T)(T param)if(is(T == int)){
return param * param;
}
void main()
{
writeln(square(123));
}
And if you want to use templates explicitly, you can use template specialization:
import std;
template square(T:int){
T square(T param){
return param * param;
}
}
void main()
{
writeln(square(123));
}
And, as you mentioned already, getting the compiler to deduce the kind of types
that are valid for a given template body is not possible right now.