Given these type definitions:
type N interface{ ~int | ~float32 | ~float64 }
type S[T any] struct {
t T
}
type myInt int
type pSpMyInt[T myInt] *S[*T]
type spMyInt[T *myInt,] S[T]
type spMyInt2[T myInt] S[*T]
I can create a var of type pSpMyInt
with
func createPS[T myInt]() pSpMyInt[T] {
var i T
s := S[*T]{t: &i}
return &s
}
But I can not figure out how to create vars of spMyInt
or spMyInt2
.
This
func createSP[T myInt]() spMyInt2[T] {
var i T
s := S[*T]{t: &i}
return s
}
fails to compile
cannot use s (variable of type S[*T]) as type spMyInt2[T] in return statement
.
CodePudding user response:
First of all, do NOT use exact type parameter constraints. It almost never makes sense. When you declare a function as createPS[T myInt]()
, the type parameter type set has cardinality 1, so it can effectively be instantiated only and ever by myInt
. You could rewrite the function like the following just as fine:
func createPS() pSpMyInt[myInt] {
var i myInt
s := S[*myInt]{t: &i}
return &s
}
With that out of the way:
The type S[*T]
is just not the same as spMyInt2[T]
. However, since spMyInt2[T]
's underlying type is S[*T]
, you can simply convert:
func createSP2[T myInt]() spMyInt2[T] {
var i T
s := S[*T]{t: &i}
return spMyInt2[T](s) // conversion
}
As for type spMyInt[T *myInt,] S[T]
(where the comma is not a typo but is needed to avoid a parsing ambiguity), the thing isn't that simple.
The problem is that a type parameter is not its type constraint. Therefore type literals can't be used to instantiate different unnamed type literals. To be clear:
// naive attempt that doesn't compile
func createSP1[T myInt]() spMyInt[*T] {
var i T
s := S[*T]{t: &i}
return spMyInt[*T](s)
}
You might think that spMyInt[T *myInt]
has a type parameter constrained to *myInt
and the function T
is constrained by the base type myInt
, therefore *T
should satisfy T *myInt
. This is not correct for the apparently unobvious reason that the type literal *T
is not equivalent to *myInt
. So actually you can't write a generic constructor for type spMyInt[T *myInt,] S[T]
.
However you are in luck because the type constraint had cardinality one. So you can just remove the type parameter:
func createSP1() spMyInt[*myInt] {
var i myInt
s := S[*myInt]{t: &i}
return spMyInt[*myInt](s)
}