英文:
How can I convert an int to a generic type containing complex128 in Go?
问题
我无法解决如何将int
转换为包含complex128
的通用类型。以下是一个示例,如果不注释掉complex128
,它将无法编译通过:
package main
import "fmt"
type val interface {
int64 | float64 | complex128
}
func f[V val](a, b V) (c V) {
q := calc()
return a * b * V(q)
}
func calc() int {
// 长时间计算,返回一个int
return 1
}
func main() {
fmt.Printf("%v\n", f(int64(1), int64(2)))
}
这是从一个更大的计算简化而来的。我尝试使用switch
语句,但是我尝试的每种语法似乎都遇到了某种形式的阻力。
如何用一个整数乘以a
和b
?
我尝试使用switch
语句根据返回变量的类型,例如any(c).(type)
,但是例如如果我有case complex128:
,它就不允许使用complex
内置函数,因为它不返回V
类型。
如果没有complex128
,上述代码将可以编译通过。
英文:
I cannot work out how to convert an int
to a generic type containing complex128
. Here is an example which doesn't compile unless the complex128
is commented out:
package main
import "fmt"
type val interface {
int64 | float64 | complex128
}
func f[V val](a, b V) (c V) {
q := calc()
return a * b * V(q)
}
func calc() int {
// lengthy calculation that returns an int
return 1
}
func main() {
fmt.Printf("%v\n", f(int64(1), int64(2)))
}
This is simplified from a much larger calculation. I've tried using a switch but every syntax I have attempted seems to meet resistance of one kind or another.
How can I multiply a
and b
with an integer?
I have tried using a switch on the type of the return variable such as any(c).(type)
but for example if I have case complex128:
then it refuses to allow the complex
builtin since it doesn't return a V
.
Without the complex128
the above will compile.
答案1
得分: 4
这个代码可以工作,但需要在switch
语句中列出每种类型:
func f[V val](a, b V) (c V) {
q := calc()
var temp any
switch any(c).(type) {
case complex128:
temp = complex(float64(q), 0)
case int64:
temp = int64(q)
default:
temp = float64(q)
}
return a * b * (temp.(V))
}
英文:
This one works but it needs to list every type in the switch
statement:
func f[V val](a, b V) (c V) {
q := calc()
var temp any
switch any(c).(type) {
case complex128:
temp = complex(float64(q), 0)
case int64:
temp = int64(q)
default:
temp = float64(q)
}
return a * b * (temp.(V))
}
答案2
得分: 4
如上所述,你的问题无法通过通用代码来解决。联合中存在complex128
,这导致无法从int
直接转换为V
。
涉及类型参数的转换只有在转换对于类型参数类型集中的所有类型都有效时才起作用,而复数类型无法转换为其他非复数数值类型。语言规范中指出:
> 非常量值 x 可以在以下任何情况下转换为类型 T:
>
> [...]
> - x 的类型和 T 都是整数或浮点数类型。
> - x 的类型和 T 都是复数类型。
虽然整数和浮点数可以相互转换,但复数类型不能。
因此,在这里无法使用泛型。如果你必须使用类型开关来强制函数工作,最好根本不使用泛型。
请注意,该函数可以很好地处理无类型常量。它会被隐式转换为表达式所需的任何类型:
func f[V val](a, b V) (c V) {
return a * b * 1
}
英文:
As stated, your issue can't be solved with actually generic code. The presence of complex128
in the union excludes a clean conversion from int
to V
.
Conversions that involve type parameters work only if the conversion is valid for all types in the type parameter type set, and complex types aren't convertible to other non-complex numeric types. The language spec states
> A non-constant value x can be converted to type T in any of these cases:
>
> [...]
> - x's type and T are both integer or floating point types.
> - x's type and T are both complex types.
While integer and floats can be converted to each other, complex types can't.
Therefore generics don't work here. If you have to specialize the function with type switches to force it to work, you are better off simply not using generics at all.
Note that the function would nicely work with an untyped constant. It would be implicitly converted to whatever type is required by the expression:
func f[V val](a, b V) (c V) {
return a * b * 1
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论