英文:
How does one allow a generic type that is convertible to a pointer to parameterise another generic type that is convertible to a pointer?
问题
从类型参数提案中,有一个有用的部分描述了如何定义类型约束,以便已经通过其指针接收器实现接口的类型仍然可以用作类型参数。例如:
type ExplainedExampleGeneric[T any] interface {
GetBool() bool
*T // 非接口类型约束元素
}
type ExplainedImpl struct{ bully bool }
func (e *ExplainedImpl) GetBool() bool { return e == nil || e.bully }
func Print[T any, PT ExplainedExampleGeneric[T]](impl T) {
fmt.Println(PT(&impl).GetBool())
}
func main() {
Print[ExplainedImpl](ExplainedImpl{}) // 输出:false
}
对于我的用例,我想将ExplainedExampleGeneric
作为另一个泛型类型的参数使用:
type UncharteredGeneric[T any, U any, V ExplainedExampleGeneric[U]] interface {
GetString() string
GetExplainedExampleGeneric() V
*T // 非接口类型约束元素
}
type ExplainedExampleGeneric[T any] interface {
GetBool() bool
*T // 非接口类型约束元素
}
这段代码可以编译通过,但是当尝试编译一个使用UncharteredGeneric
类型的函数时,会出现以下错误:
./prog.go:35:40: 有2个参数,但有3个类型参数
./prog.go:36:17: 无法将 &impl(类型为*T)转换为类型PT
最后,当我尝试调用这个函数时,无法推断出我的类型 链接到 playground:
./prog.go:36:40: 有2个参数,但有3个类型参数
./prog.go:37:17: 无法将 &impl(类型为*T)转换为类型PT
./prog.go:42:50: 无法推断出PT(prog.go:36:37)
有什么想法我做错了什么吗?似乎应该是可能的,但我不确定我在这里漏掉了什么,非常感谢任何帮助。
英文:
From the type parameters proposal, there is a useful section describing how one should define a type constraint such that a type that already implements the interface via it's pointer receivers can still be used as a type parameter, for example:
type ExplainedExampleGeneric[T any] interface {
GetBool() bool
*T // non-interface type constraint element
}
type ExplainedImpl struct{ bully bool }
func (e *ExplainedImpl) GetBool() bool { return e == nil || e.bully }
func Print[T any, PT ExplainedExampleGeneric[T]](impl T) {
fmt.Println(PT(&impl).GetBool())
}
func main() {
Print[ExplainedImpl](ExplainedImpl{}) // Prints: false
}
For my use-case, I want to use this ExplainedExampleGeneric
as a parameter to another generic type:
type UncharteredGeneric[T any, U any, V ExplainedExampleGeneric[U]] interface {
GetString() string
GetExplainedExampleGeneric() V
*T // non-interface type constraint element
}
type ExplainedExampleGeneric[T any] interface {
GetBool() bool
*T // non-interface type constraint element
}
This compiles, however, when trying to compile a function to utilise this UncharteredGeneric
type, I get the following errors:
./prog.go:35:40: got 2 arguments but 3 type parameters
./prog.go:36:17: cannot convert &impl (value of type *T) to type PT
func UncharteredPrint[T any, U any, PT UncharteredGeneric[T, U]](impl T) { -> got 2 arguments but 3 type parameters
fmt.Println(PT(&impl).GetExplainedExampleGeneric().GetBool()) -> cannot convert &impl (value of type *T) to type PT
}
Finally, when I try to call this function, my type is unable to be inferred link to playground:
./prog.go:36:40: got 2 arguments but 3 type parameters
./prog.go:37:17: cannot convert &impl (value of type *T) to type PT
./prog.go:42:50: cannot infer PT (prog.go:36:37)
package main
import "fmt"
type UncharteredGeneric[T any, U any, V ExplainedExampleGeneric[U]] interface {
GetString() string
GetExplainedExampleGeneric() V
*T // non-interface type constraint element
}
type ExplainedExampleGeneric[T any] interface {
GetBool() bool
*T // non-interface type constraint element
}
type UncharteredImpl struct{ some string }
func (e *UncharteredImpl) GetExplainedExampleGeneric() ExplainedImpl { return ExplainedImpl{} }
func (e *UncharteredImpl) GetString() string {
if e == nil {
return ""
}
return e.some
}
type ExplainedImpl struct{ bully bool }
func (e *ExplainedImpl) GetBool() bool { return e == nil || e.bully }
func Print[T any, PT ExplainedExampleGeneric[T]](impl T) {
fmt.Println(PT(&impl).GetBool())
}
func UncharteredPrint[T any, U any, PT UncharteredGeneric[T, U]](impl T) { -> got 2 arguments but 3 type parameters
fmt.Println(PT(&impl).GetExplainedExampleGeneric().GetBool()) -> cannot convert &impl (value of type *T) to type PT
}
func main() {
Print[ExplainedImpl](ExplainedImpl{})
UncharteredPrint[UncharteredImpl, ExplainedImpl](UncharteredImpl{}) -> cannot infer PT (prog.go:36:37)
}
Any idea what I'm doing wrong? Seems like it should be possible but I'm unsure of what I'm missing here, any help would be greatly appreciated.
答案1
得分: 2
首先,接口UncharteredGeneric
是一个带参数的类型,你必须明确提供所有三个类型参数。
因此,在UncharteredPrint
函数的类型参数列表中,PT
应该是:
PT UncharteredGeneric[T, U, V]
现在,V
是什么?如UncharteredGeneric
自己的类型参数列表所示,V
必须满足ExplainedExampleGeneric[U]
,因此我们这样定义它。完整的签名变为:
UncharteredPrint[T any, U any, V ExplainedExampleGeneric[U], PT UncharteredGeneric[T, U, V]](impl T)
你不能直接使用ExplainedExampleGeneric[U]
来实例化UncharteredGeneric
,因为ExplainedExampleGeneric
包含类型元素*T
;你只能将其用作V
的约束条件。
最后,在所有这些之后,PT
将被推断为*UncharteredImpl
,但这还没有实现UncharteredGeneric
——V
被实例化为*ExplainedImpl
,但该方法声明为GetExplainedExampleGeneric() ExplainedImpl
。你还需要修复方法签名以返回指针类型:
func (e *UncharteredImpl) GetExplainedExampleGeneric() *ExplainedImpl { return &ExplainedImpl{} }
然后,它可以编译和运行:https://go.dev/play/p/zCZd53ys-5J
英文:
First, the interface UncharteredGeneric
is a parametrized type, you must explicitly supply all three type parameters.
Therefore in UncharteredPrint
function type parameter list, PT
should be:
PT UncharteredGeneric[T, U, V]
Now what is V
? As seen in UncharteredGeneric
own type param list, V
must satisfy ExplainedExampleGeneric[U]
, hence this is how we define it. The full signature becomes:
UncharteredPrint[T any, U any, V ExplainedExampleGeneric[U], PT UncharteredGeneric[T, U, V]](impl T)
You can't use directly ExplainedExampleGeneric[U]
to instantiate UncharteredGeneric
because ExplainedExampleGeneric
includes the type element *T
; you can only use it as a constraint for V
.
Finally, after all this PT
would be inferred as *UncharteredImpl
, but this doesn't yet implement UncharteredGeneric
— V
is instantiated with *ExplainedImpl
, but the method is declared as GetExplainedExampleGeneric() ExplainedImpl
. You have also to fix the method signature to return the pointer type:
func (e *UncharteredImpl) GetExplainedExampleGeneric() *ExplainedImpl { return &ExplainedImpl{} }
Then, it compiles and runs: https://go.dev/play/p/zCZd53ys-5J
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论