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]));
```