On Sunday, 1 May 2022 at 03:57:12 UTC, Elfstone wrote:
    module test;

    struct MatrixImpl(S, size_t M, size_t N)
    {
    }

    template Vector(S, size_t N)
    {
        alias Vector = MatrixImpl!(S, 1, N);
    }

    @nogc
S dot1(S, size_t N)(in Vector!(S, N) lhs, in Vector!(S, N) rhs)
    {
        return 0;
    }

    @nogc
S dot2(S, size_t N)(in MatrixImpl!(S, 1, N) lhs, in MatrixImpl!(S, 1, N) rhs)
    {
        return 0;
    }

    unittest
    {
        import std.stdio;

        Vector!(float, 2) a, b;
dot1(a, b); // Error: none of the overloads of template `test.dot1` are callable using argument types `!()(MatrixImpl!(float, 1LU, 2LU), MatrixImpl!(float, 1LU, 2LU))` // Candidate is: `dot1(S, ulong N)(in Vector!(S, N) lhs, in Vector!(S, N) rhs)`
        dot2(a, b); // compiles
static if (is(Vector!(float, 2) == MatrixImpl!(float, 1, 2)))
        {
            writeln("WTH"); // prints
        }
    }

It's natural to declare it the way dot1 is declared, isn't it?
Is this a bug?
Or I simply can't assume alias works the way I thought it would.
Can I work around it, without falling back to the abominable dot2?

Template deduction for aliased function parameter is a very tricky argument and it's not so simple to handle in certain cases. Consider for example this code:

```d
    template MyAlias(T){
      alias MyAlias = int;
    }

    T simp(T)(MyAlias!T val){
      return T.init;
    }

    int main(){
      simp(3);//Impossible to deduce T
simp( cast(MyAlias!string) 4);//Also invalid since MyAlias!string is exactly int
      simp!string(4);//Ok, no parameter deduction
    }
```

Instead to use aliases it's better (both in D and in C++) to use constraints/concepts.

Reply via email to