Cannot always deduce template arguments when using implicitly cast array literals
Paul Backus
snarwin at gmail.com
Fri Jul 23 14:41:41 UTC 2021
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]));
```
More information about the Digitalmars-d-learn
mailing list