On Tuesday, 21 March 2023 at 07:51:50 UTC, FeepingCreature wrote:
> [snip]
What you want needs a fundamentally new language feature; something like typeclasses. Now there's an argument to be made to add typeclasses to the language, they would make ranges a lot more swanky for instance, but it's just not a matter of making template inference marginally more powerful.
There are a lot of things that D's template aliases could do if resolution were a solved problem (I get that a big problem is that it is too powerful).
Below (taken from [1]) is a way to use something like concepts in D (b/c you can impose any constraint you want on the template or on static if's within the template). You can place requirements on T (in this case just that it is an int) and if it succeeds, then you have your alias. In a more complicated case, static if's could provide better error messages.
template Foo(T)
if (is(T == int))
{
alias Foo = T;
}
void foo(T)(Foo!T x) { }
void main() {
Foo!int x;
foo!int(x); //compiles
foo(x); //doesn't compile but ideally should
foo(1.0); //doesn't compile and shouldn't
}
Unfortunately, an alias this approach wouldn't be sufficient in this case since alias this requires creating a whole new type. That means if you want the functionality to work with the original type, then you need to have it be implicitly convertible to the original type and you're still stuck writing that type out.
struct Matrix(S, size_t M, size_t N) {}
struct Vec3(S) {
Matrix!(S, 3, 1) data;
alias data this;
}
void foo(U : Matrix!(V, 3, 1), V)(U u) {}
void bar(U)(Vec3!U v) {}
void main()
{
import std.stdio;
Matrix!(float, 3, 1) u;
Vec3!float v;
foo(u);
foo(v);
//bar(u); //fails to compile
bar(v);
}
[1] https://forum.dlang.org/post/uzvxrqywxfqmoplurfcf@forum.dlang.org