将类型之间的关系指定为特征或宏

时间:2017-01-20 03:16:23

标签: rust traits

我想做以下工作:

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 s的存在:即X: CanBeAdded暗示f64: Add<X>。虽然我可以将边界添加到函数的where子句中,如下所示:

fn add2<X>(x: X) where f64: Add<X> { }

我有很多,所以它变得笨拙,我宁愿不要一遍又一遍地重复这些界限。有一个很好的解决方案吗?例如,是否可以包含一个扩展为一系列where子句的宏?

1 个答案:

答案 0 :(得分:0)

实际上,随机类型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的类型自动实现特征,但关系反转:

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) {
}