2016-10-13 22 views
7

在創建該存儲DST一個結構(例如,原始片),我可以使用正常的#[derive(Eq, PartialEq, Ord, PartialOrd)]設施讓我的類型這種特質的實現:當我嘗試在未定義的類型上手動實現Ord和Eq時,爲什麼我不能滿足'特性綁定'[T]:std :: marker :: Sized`?

#[derive(PartialEq, Eq, PartialOrd, Ord)] 
struct A([u8]); 

但是,如果我手動實現它們,那麼編譯器會抱怨說,我喜歡的類型不實現Sized

struct A([u8]); 

impl AsRef<[u8]> for A { 
    fn as_ref(&self) -> &[u8] { 
     &self.0 
    } 
} 

impl<S: AsRef<[u8]>> PartialEq<S> for A { 
    fn eq(&self, other: &S) -> bool { 
     self.0.eq(other.as_ref()) 
    } 
} 

impl Eq for A { } 

impl<S: AsRef<[u8]>> PartialOrd<S> for A { 
    fn partial_cmp(&self, other: &S) -> Option<Ordering> { 
     let slice: &[u8] = &self.0; 
     slice.partial_cmp(other.as_ref()) 
    } 
} 

impl Ord for A { 
    fn cmp(&self, other: &Self) -> Ordering { 
     self.partial_cmp(&other).unwrap() 
    } 
} 

編譯結果:

rustc 1.12.0 (3191fbae9 2016-09-23) 
error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied 
    --> <anon>:20:6 
    | 
20 | impl Eq for A { } 
    |  ^^ 
    | 
    = note: `[u8]` does not have a constant size known at compile-time 
    = note: required because it appears within the type `A` 
    = note: required because of the requirements on the impl of `std::cmp::PartialEq` for `A` 
    = note: required by `std::cmp::Eq` 

error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied 
    --> <anon>:29:6 
    | 
29 | impl Ord for A { 
    |  ^^^ 
    | 
    = note: `[u8]` does not have a constant size known at compile-time 
    = note: required because it appears within the type `A` 
    = note: required because of the requirements on the impl of `std::cmp::PartialOrd` for `A` 
    = note: required by `std::cmp::Ord` 

如果我創建一個確實具有固定大小(例如,大小)的類型的變體。通過將它轉換成一個固定大小的數組),然後我可以手動實現特徵沒有問題。

struct B([u8; 5]); 

impl AsRef<[u8]> for B { 
    fn as_ref(&self) -> &[u8] { 
     &self.0 
    } 
} 

impl<S: AsRef<[u8]>> PartialEq<S> for B { 
    fn eq(&self, other: &S) -> bool { 
     self.0.eq(other.as_ref()) 
    } 
} 

impl Eq for B { } 

impl<S: AsRef<[u8]>> PartialOrd<S> for B { 
    fn partial_cmp(&self, other: &S) -> Option<Ordering> { 
     let slice: &[u8] = &self.0; 
     slice.partial_cmp(other.as_ref()) 
    } 
} 

impl Ord for B { 
    fn cmp(&self, other: &Self) -> Ordering { 
     self.partial_cmp(&other).unwrap() 
    } 
} 

Here is a playground link showing the issue

我的問題是 - 如何在我的自定義DST實現OrdEq,這樣我可以採取的事實,即我可以partial_cmp/eq任何AsRef<[u8]>,而且還用它來執行邊界爲Ord/Eq特質的實現,就像我在struct B中做的那樣?

+1

@matthieuM,的['PartialOrd']的定義(https://doc.rust-lang.org/std/ cmp/trait.PartialOrd.html)特性需要'PartialEq',所以從我的理解來看,我認爲'#[derive(PartialOrd)]'也需要'#[derive(PartialEq)]'。 – burtonageo

+1

@MatthieuM。我看不出有什麼問題。 'PartialOrd'需要'PartialEq'。 'struct A(u8);'發生同樣的事情。 – Dogbert

+1

@Dogbert:我在某個時候有點奇怪......但是恐怕之後我減少了太多。 –

回答

7

問題是S: AsRef<[u8]>默認情況下也會限制SSized類型。您需要使用?Sized來選擇退出。

所有泛型類型參數隱含有約束Sized,所以?Sized可以用來退出隱式綁定的。

From the Rust Book

下面我編譯罰款:

use std::cmp::Ordering; 

struct A([u8]); 

impl AsRef<[u8]> for A { 
    fn as_ref(&self) -> &[u8] { 
     &self.0 
    } 
} 

impl<S: AsRef<[u8]> + ?Sized> PartialEq<S> for A { 
    fn eq(&self, other: &S) -> bool { 
     self.0.eq(other.as_ref()) 
    } 
} 

impl Eq for A {} 

impl<S: AsRef<[u8]> + ?Sized> PartialOrd<S> for A { 
    fn partial_cmp(&self, other: &S) -> Option<Ordering> { 
     let slice: &[u8] = &self.0; 
     slice.partial_cmp(other.as_ref()) 
    } 
} 

impl Ord for A { 
    fn cmp(&self, other: &Self) -> Ordering { 
     self.partial_cmp(&other).unwrap() 
    } 
} 

Demo

相關問題