【发布时间】:2020-04-18 14:19:25
【问题描述】:
我正在尝试创建一个对通用数字类型进行抽象的特征。指定我希望特征需要T + T(即T: Add<T>)很容易。我什至可以在特征中指定T + &T,然后在实现该特征的某种类型的泛型函数中使用它。
但是,当我尝试为特征添加&T + T(即for<'a> &'a Self: Add<Self>)和&T + &T 的约束时,我遇到了问题。奇怪的是,在为数字特征编写毯子impl 时,以及为任何类型的特征编写通用函数时,我可以毫无问题地指定这些相同的约束,但我无法让编译器让我只指定这些而是在 trait 上约束一次。
简化示例
use std::ops::Add;
trait Numeric where
Self: Sized,
// T + T
Self: Add<Output = Self>,
// T + &T
Self: for<'a> Add<&'a Self, Output = Self>,
// &T + T
// should specify &T + T on this trait but instead causes compile
// errors everywhere I try to use Numeric claiming no implementation
// for &T + T
// for<'a> &'a Self: Add<Self, Output = Self>,
// &T + &T
// should specify &T + &T on this trait but instead causes compile
// errors everywhere I try to use Numeric claiming no implementation
// for &T + &T
// for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>,
{}
impl <T> Numeric for T where
// T + T
T: Add<Output = Self>
+ Sized,
// T + &T
for<'a> T: Add<&'a T, Output = T>,
// &T + T
for<'a> &'a T: Add<T, Output = T>,
// &T + &T
for<'a, 'b> &'a T: Add<&'b T, Output = T>,
{}
// works
fn generic_add_0<T: Numeric>(a: T, b: T) -> T {
a + b
}
// works
fn generic_add_1<T: Numeric>(a: T, b: &T) -> T {
a + b
}
// doesn't infer &T + T from the trait?
fn generic_add_2<T: Numeric>(a: &T, b: T) -> T {
a + b
}
// doesn't infer &T + &T from the trait?
fn generic_add_3<T: Numeric>(a: &T, b: &T) -> T {
a + b
}
// works
fn generic_add_4<T: Numeric>(a: &T, b: &T) -> T
// I want to not have to specify this every time I use Numeric,
// I want Numeric to imply this constraint for me
where for<'a, 'b> &'a T: Add<&'b T, Output = T> {
a + b
}
fn main() {
generic_add_0(1.0, 2.0);
generic_add_1(1.0, &2.0);
generic_add_2(&1.0, 2.0);
generic_add_3(&1.0, &2.0);
generic_add_4(&1.0, &2.0);
}
【问题讨论】:
-
我认为这是known issue。
-
通过查看一些图书馆是如何做到这一点的,我在
num-traits中发现了这个测试,其中RefNum似乎能够表达&T + &T 约束:docs.rs/num-traits/0.2.10/src/num_traits/lib.rs.html#547,我不知道t 真的理解 docs.rs/num-traits/0.2.10/src/num_traits/lib.rs.html#112 的 trait 声明,但它似乎有点像我所追求的?