2017-05-15 38 views
1
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我應該能夠實現RandAllValues因爲我的箱子中定義了AllValues。這實際上是否符合連貫性/孤兒impl的規則?如果是這樣,那麼實施AllValues的東西實施Rand的正確方法是什麼?

+0

我認爲這個實例將不得不被定義在哪裏'Rand'是...... – Alec

回答

2

I should be able to implement Rand for AllValues since AllValues is defined in my crate.

不行,你只能實現自己的特質AllValues你沒有定義類型。你不能做邏輯跳躍來實現你也沒有定義的無關特質。

有兩個方面的考慮要記住:

  • 如果你的特點是公開的(它是根據您所提供的代碼),你是不是能夠實現特質唯一的一個。你的箱子的消費者可能能夠實現它們的類型,他們也可能決定實施Rand
  • 蘭特集團可能決定在未來的某個時間實施RandT

What is the right way to implement Rand for things that implement AllValues ?

我不相信這是一個。我只是介紹一個包裝類型,它包含一個值或一個實現你的特質的值的引用,併爲此實現Rand

1

我現在看到我的解釋錯誤在哪裏。從the traits section of the book報價:

There’s one more restriction on implementing traits: either the trait or the type you’re implementing it for must be defined by you. Or more precisely, one of them must be defined in the same crate as the impl you're writing.

(強調)

由於我是想實現一個特點,我必須看過,由於「無論是性狀或特質你實現它 」。 This discussion about an eventually implemented rfc特別提到了我提交的一個類似案例:impl<T: Copy> Clone for T作爲不被允許的東西。

按照其他地方的建議創建包裝類型是解決此問題的一種方法。假設類型實現的所有權允許它,爲每個具體實例明確地實現特徵(可選地將代碼與宏集成),如建議here是另一個。