繁体   English   中英

无法为实现我拥有的特征的所有类型实现我不拥有的特征

[英]Can't implement a trait I don't own for all types that implement a trait I do own

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 {
    | ^

根据这里提到的实现特性的限制,我应该能够为AllValues实现Rand ,因为AllValues是在我的箱子中定义的。 一致性/孤儿impl规则实际上允许这样做吗? 如果是这样,为实现AllValues事物实现Rand的正确方法是什么?

我应该能够为AllValues实现Rand ,因为AllValues是在我的箱子中定义的。

不,您只能为未定义的类型实现自己的特征AllValues 你不能从逻辑上跳到实现一个你也没有定义的无关特征。

有两个注意事项需要记住:

  • 如果您的特征是公开的(它基于您提供的代码),那么您并不是唯一可以实现该特征的人。 您的 crate 的消费者可能能够为他们自己的类型实现它,他们也可能决定在其中实现Rand
  • rand crate 可能会决定在未来的某个时间为T实现Rand

为实现AllValues事物实现Rand的正确方法是什么?

我不相信有一个。 我只是介绍一个包装器类型,它保存一个值或一个值的引用,该值实现了您的特征并为此实现了Rand

也可以看看:

我现在明白我的解释错误在哪里。 引用本书的特征部分

实现 trait 还有一个限制:要么是 trait 要么是你要实现它的类型必须由你定义。 或者更准确地说,其中之一必须与您正在编写的 impl 定义在同一个 crate 中。

(加了重点。)

由于我试图实现一个特征,我必须将其理解为“特征或您正在为其实现特征”。 这个关于最终实现的 rfc 的讨论特别提到了一个与我提出的类似的案例: impl<T: Copy> Clone for T是不允许的。

按照其他地方的建议创建包装器类型是解决此问题的一种方法。 假设类型实现的所有权允许它,为每个具体实例显式实现特征,(可选地用宏压缩代码),正如这里建议的那样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM