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
规则允许的吗?如果是这样,对于实施Rand
的内容,实施AllValues
的正确方法是什么?
答案 0 :(得分:2)
我应该能够为
Rand
实施AllValues
,因为我的箱子中定义了AllValues
。
不,您只能为未定义的类型实现自己的特征AllValues
。你不能进行逻辑跳转来实现你也没有定义的无关特征。
要记住两个注意事项:
Rand
!Rand
实施T
。为实施
Rand
的内容实施AllValues
的正确方法是什么?
我不相信有一个。我只是介绍一个包装器类型,它包含一个值或对一个实现你的特征的值的引用,并为此实现Rand
。
另见:
答案 1 :(得分:1)
我现在看到我的解释错误在哪里。引自the traits section of the book:
实施特征还有一个限制:要么是特质 或者你实现它的类型必须由你定义。或者更多 确切地说,其中一个必须与impl在同一个箱子中定义 你正在写作。
(强调补充。)
因为我试图实现一个特性,所以我必须把它读作“要么是>>要实现它的特性或特征”。 This discussion about an eventually implemented rfc特别提到了与我提出的案例相似的案例:impl<T: Copy> Clone for T
是不允许的事情。
如其他地方所建议的那样创建包装器类型是解决此问题的一种方法。假设类型实现的所有权允许它,为每个具体实例显式地实现特征(可选地用宏来压缩代码),如建议的那样here是另一个。