我想做如下工作:

use std::ops::Add;

trait CanBeAdded: Sized where f64: Add<Self> {}

fn add2<X: CanBeAdded>(x: X) {}

fn main() {}

以上编译失败:
error[E0277]: the trait bound `f64: std::ops::Add<X>` is not satisfied
 --> src/main.rs:5:1
  |
5 | fn add2<X: CanBeAdded>(x: X) {}
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Add<X>` is not implemented for `f64`
  |
  = help: consider adding a `where f64: std::ops::Add<X>` bound
  = note: required by `CanBeAdded`

Playground link
我试图通过一个特性来断定某些impl的存在:即X: CanBeAdded暗示f64: Add<X>。虽然我可以像这样给函数的where子句添加边界:
fn add2<X>(x: X) where f64: Add<X> { }

我有很多这样的球,所以很难控制,我不想一遍又一遍地重复这些球。有好的解决办法吗?例如,是否可以包含扩展为一系列where子句的宏?

最佳答案

实际上,随机类型X不太可能是这样的f64: Add<X>
考虑到f64是一个内置的模块,唯一可以为Add定义f64实现的模块是定义Add的模块。我们可以查看listed implementations here
impl Add<f64> for f64
impl<'a> Add<&'a f64> for f64
仅此而已。
尽管如此,如果这是你想要的,你可以用不同的方式来定义特质。
首先,我们定义了一个新的标记性状。它本身很无趣,因为它完全没有方法:

trait ReverseAdd<T> { type Output; }

然后,我们添加了一个覆盖实现,以自动实现实现Add的任何类型的trait,但是关系颠倒了:
impl<T, U> ReverseAdd<T> for U where T: Add<U> {
    type Output = <T as Add<U>>::Output;
}

最后,我们用它作为我们的边界:
fn add2<X: ReverseAdd<f64>>(x: X) {
}

关于rust - 将类型之间的关系指定为特征或宏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41755504/

10-10 19:35