假设我想编写一个通用函数,该函数接受一些K
类型的值,并将其与f64
进行可交换地相乘。以下作品:
fn generic1<K>(a: K, b: f64) -> K
where
K: Mul<f64, Output = K> + Add<K, Output = K> + Copy,
f64: Mul<K, Output = K>,
{
a * b + b * a
}
但是,我现在不再能够在同一个函数中将两个浮点数相乘。实际上,似乎绑定(bind)的
f64: Mul<K, Output = K>
覆盖/隐藏(?)impl impl Mul<f64> for f64
。这是一个例子:fn generic2<K>(a: K, b: f64) -> K
where
K: Mul<f64, Output = K> + Add<K, Output = K> + Add<f64, Output = K> + Copy,
f64: Mul<K, Output = K>,
{
a * b + b * a + b * b
}
这将导致以下编译器错误:
|
16 | a * b + b * a + b * b
| ^ expected type parameter, found f64
|
= note: expected type `K`
found type `f64`
(playground link),即
f64 * <whatever>
现在仅适用于<whatever>
类型的K
。作为一种解决方法,我可以使用完全限定的语法
<f64 as Mul<f64>>::mul(b, b)
,但这非常丑陋。感觉编译器应该能够看到它可以使用f64
类型的输出,因此可以使用f64 * f64
的实现而不是f64 * K
。我想做的一个不太抽象的示例:
K
可以是向量类型,也可以是标量类型,并且我希望能够以通用方式对其进行可交换标量乘法。这里发生了什么?为什么我不能再乘
b * b
?更新:@Ömer-erden注意到它在明确指定
f64: Mul<f64, Output = f64>
时也有效。不幸的是,导入 alga
crate时,该解决方法无法正常工作-请参阅updated playground link。我不确定海藻能做什么来打破已经很奇怪的行为。正如Ömer已经指出的那样,这似乎更多是类型检查器的错误或局限性,而不是藻类/其他方面的错误,因为理想情况下,对于任何内置类型,没有代码应该能够破坏
impl Mul<f64, Output = f64>
或类似代码的解析度。 最佳答案
这是一个约束,告诉您当K
是正确的操作数时,您可以将f64
与K
相乘,输出将是K
。还告诉f64
必须实现Mul<K, Output = K>
f64: Mul<K, Output = K>,
我还不知道,这可能是由于类型检查器或bug的功能有限而导致的,但是由于
Mul<f64, Output = f64>
的约束,在f64
上实现Mul<K, Output = K>
的方式变得模棱两可。如果您明确说明预期的行为,在您的情况下为
Mul<f64, Output = f64>
:fn generic2<K>(a: K, b: f64) -> K
where
K: Mul<f64, Output = K> + Add<K, Output = K> + Add<f64, Output = K> + Copy,
f64: Mul<K, Output = K> + Mul<f64, Output = f64>,
{
a * b + b * a + b * b
}
它会按预期工作。
Playground
关于generics - 一般在Rust中乘以不同类型的值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58657264/