On Friday, 23 July 2021 at 13:53:27 UTC, Rekel wrote:
After simplifying a part of my code I found the following code cannot deduce the template arguments, but I have no clue why.

```d
void foo(L : T[L1][L2], uint L1, uint L2, T, R:
                T[L1])(const L left, const R right) {
        // Function
}

void bar(uint L)(float[L] l) {
        // Function
}

void main(string[] args) {
bar([1.0f, 2, 3, 4, 5, 6, 7, 8]); // implicitly cast to float[8], works
        float[4][1] l = [[1, 2, 3, 4]];
foo!(typeof(l), 4, 1, float, float[4])(l, [1.0f, 2, 3, 4]); // also works foo(l, [1.0f, 2, 3, 4]); // cannot deduce function from argument types (?)
}
```

As one can see, implicitly casting array literals in templates works fine in the case of bar, as does explicit use of templates in the case of foo, but for some reason foo does not manage to deduce its arguments like bar does.

Looks like the problem is that the compiler is interpreting `[1.0f, 2, 3, 4]` as a dynamic array (`float[]`) instead of a static array (`float[4]`).

Array literals are treated as dynamic arrays by default, and as static arrays only in specific contexts where the compiler is able to determine that a static array is required. Unfortunately, the algorithm it uses for this is not very sophisticated, and does not take type specializations (like `R : T[L1]`) into account.

There are two ways you can solve this. The first is to change the type of `right` from `const R` to `const T[L1]`, which removes the type specialization:

```d
void foo(L : T[L1][L2], uint L1, uint L2, T)
        (const L left, const T[L1] right)
{
        // Function
}
```

The second is to use `std.array.staticArray` to manually cast the array literal to a static array:

```d
    import std.array: staticArray;
    foo(l, staticArray!([1.0f, 2, 3, 4]));
```

Reply via email to