func GAddAll[E int, S ~[]E](e E, s S) S { copyS := make(S, len(s)) for i, v := range s { copyS[i] = v + e } return copyS}对于上面的代码,如果我这样实例化,运行时会报错(cannot infer S)b := GAddAll[int]fmt.Printf("%v", b(3, []int{1, 2}))但它像这样工作得很好fmt.Printf("%v", GAddAll[int](3, []int{1, 2}))我想知道为什么。
1 回答
富国沪深
TA贡献1790条经验 获得超9个赞
实例化失败,因为S ~[]E
有一个近似约束,并且没有足够的类型信息来实例化S
。
当您分配函数值时:
b := GAddAll[int]
该函数已经被实例化。引用规范:
一个不被调用的泛型函数需要一个类型参数列表来实例化;如果列表是部分的,则所有剩余的类型参数必须是可推断的。
然而S
不可推论。编译器唯一可用的信息是类型参数E
。在第一遍替换之后,编译器只能推断出约束~[]E
,现在是~[]int
,但类型参数S
仍然未知。
鉴于带有波浪号 ( ~
) 的近似类型集实际上是无限的,因此无法最终确定什么S
是——它可能是type FooSlice []int
——并且实例化失败。
因此,如果您需要传递函数值,则必须通过提供两种类型参数来实例化:
b := GAddAll[int, []int] // ok fmt.Printf("%v", b(3, []int{1, 2}))
而是使用调用表达式:
GAddAll[int](3, []int{1, 2})
编译器仍然不能S
从类型参数中推断出来int
,但它可以从非类型参数中推断出来[]int{1,2}
,然后实例化函数。
被调用的泛型函数可以提供(可能是部分)类型参数列表,或者如果省略的类型参数可以从普通(非类型)函数参数中推断出来,则可以完全省略它。
作为澄清,如果您要从 中删除波浪号S ~[]E
,如下所示:
func GAddAll[E int, S []E](e E, s S) S {}
仅提供 即可成功推理E
,因为 的约束类型集的S
基数为 1(精确类型)。
- 1 回答
- 0 关注
- 74 浏览
添加回答
举报
0/150
提交
取消