Trying to do alias template deduction myself.

Elfstone elfstone at yeah.net
Fri Mar 31 05:19:48 UTC 2023


Related thread: 
https://forum.dlang.org/thread/wgvtwckvjyhnbpcuyyqy@forum.dlang.org

It seems `dtemplate.deduceType` does all the deduction for both 
`is` and IFTI. I can already add a better error message, right 
before "goto Lnomatch":
`cannot deduce the instantiation of an alias template` (is that 
the right term?)
This will better explain to new users why it really fails:
`NOT because no callable candidate exists, but because D never 
tried to do anything about an alias template to find the match. 
So try instantiating the function explicitly then it will work.`

But my goal is:
```D
struct Matrix(U, size_t M, size_t N)
{
     U[M * N] data;
}

alias Vector3(U) = Matrix!(U, 3, 1);
alias Vec3(U) = Vector3!U;
alias Vec3Alt = Vector3;
alias Vec3Var(U...) = Vector3!(U);
alias V3(U) = Vector3!U;

alias Identity(U) = int;

void foo1(U)(in Vector3!U a)
{
}

void foo2(U)(in Vec3!U v)
{
}

void foo2Alt(U)(in Vec3Alt!U v)
{
}

void foo3Var(U...)(Vec3Var!(U))
{
}

void foo3(U)(in V3!U)
{
}

void foo4(U)(Identity!U u)
{
}

void main()
{
     auto instVar = Vector3!float();
     // The current behaviour is: deduction for alias template 
will always fail.
     // foo1(instVar); // expect OK
     // foo2(instVar); // expect OK
     // foo2Alt(instVar); // expect OK
     // foo3Var(instVar); // expect OK
     // foo3(instVar); // expect OK

     // foo4(Identity!int()); // let it fail

     // import std.regex;
     // import std.traits;
     // static assert(isInstanceOf!(Regex, Regex!char)); // now 
fails, not sure it can be fixed along
}
```

How I like it to behave is based on what C++ offers.

```C++
template <typename T, size_t M, size_t N>
struct Matrix {
	T data[M * N];
};

template<typename T, size_t M, size_t N>
using Mat = Matrix<T, M, N>;

template <typename T>
using Vector3 = Matrix<T, 3, 1>;

template <typename T>
using Vec3 = Vector3<T>;

template <typename T>
using Identity = int;

template <typename T>
void foo1(const Vector3<T>& v) {

}

template <typename T>
void foo2(const Vec3<T>& v) {

}

template <typename T, size_t M, size_t N>
void foo3(const Mat<T, M, N>& v) {

}

template <typename T>
void foo4(const Identity<T> id) {

}

int main() {
	foo1(Vector3<float>()); // OK
	foo2(Vector3<float>()); // OK
	foo3(Vector3<float>()); // OK

	// Let it fail
	// foo4(Identity<int>()); // no matching overloaded function 
found.
}
```


My current idea is to "expand" the alias with its to-be-matched 
parameter(s) to the fullest form if possible (for example, V3!U > 
Vec3!U > Matrix!(U, 3, 1)), then go to the parameter matching 
routine.

It seems possible, if I just follow 
`TemplateDeclaration.onemember` and expand the expression level 
by level, give up when running into overloads, conditions, or 
anything too complicate (I'm not sure if `onemember` ensures no 
conditions). I could be wrong, but based on my few hours of 
reading the code and really helpful comments in the forum, I 
believe people who are more familiar with the compiler code can 
implement it instantantly.

I'm making this post not to promise to fix it (I'll try), but to 
gather opinions:
Do you think such behaviour in D is desirable (regardless of how 
I imagine it can be implemented)?
What do I miss?





More information about the Digitalmars-d mailing list