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

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}))

我想知道为什么。


紫衣仙女
浏览 120回答 1
1回答

富国沪深

实例化失败,因为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(精确类型)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go