为了账号安全,请及时绑定邮箱和手机立即绑定

具有近似约束的函数值导致实例化失败

具有近似约束的函数值导致实例化失败

Go
紫衣仙女 2023-01-03 15:58:52
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(精确类型)。


查看完整回答
反对 回复 2023-01-03
  • 1 回答
  • 0 关注
  • 74 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信