pub trait AllValues {
fn all_values() -> Vec<Self> where Self: std::marker::Sized;
}
use rand::Rand;
use rand::Rng;
impl<T: AllValues + Sized> Rand for T {
fn rand<R: Rng, T>(rng: &mut R) -> T {
let values = T::all_values();
let len = values.len();
if len == 0 {
panic!("Cannot pick a random value because T::all_values() returned an empty vector!")
} else {
let i = rng.gen_range(0, len);
values[i]
}
}
}
上面的代码产生以下编译时错误:
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter
--> src/lib.rs:137:1
|
137 | impl<T: AllValues + Sized> Rand for T {
| ^
根据here提到的实施特性的限制,我应该能够为Rand
实施AllValues
,因为AllValues
是在我的箱子里定义的。这实际上是由连贯/孤儿impl
s规则允许的吗?如果是这样,为实施Rand
的事情实施AllValues
的正确方法是什么?
我应该能够为
Rand
实施AllValues
,因为AllValues
是在我的箱子里定义的。
不,您只能为未定义的类型实现自己的特性AllValues
。您无法进行逻辑跳转以实现您也未定义的无关特征。
要记住两个注意事项:
Rand
!Rand
实施T
。对于实现
Rand
的东西,实施AllValues
的正确方法是什么?
我不相信有一个。我只是介绍一个包装类型,它包含一个值或对一个实现你的特征的值的引用,并为此实现Rand
。
也可以看看:
我现在看到我的解释错误在哪里。引自the traits section of the book:
实施特征还有一个限制:要么是要实现特征,要么是你要实现它的类型。或者更确切地说,其中一个必须与您正在编写的impl在同一个箱子中定义。
(重点补充。)
由于我试图实现一个特征,我必须把它读作“你要实现它的特征或特征”。 This discussion about an eventually implemented rfc特别提到了一个类似于我提出的案例:impl<T: Copy> Clone for T
是不允许的。
如其他地方所建议的那样创建包装器类型是解决此问题的一种方法。假设类型实现的所有权允许它,为每个具体实例显式实现特征(可选地用宏来缩小代码),如同建议的here是另一个。