2016-11-19 73 views
0

我寫了一個特點,指定類似於那些Vec一些方法:如何自動實現FromIterator?

pub trait Buffer { 
    type Item; 
    fn with_capacity(c: usize) -> Self; 
    fn push(&mut self, item: Self::Item); 
} 

我想實現FromIterator爲實現Buffer所有類型,如下所示:

impl<T> iter::FromIterator<T::Item> for T 
    where T: Buffer 
{ 
    fn from_iter<I>(iter: I) -> Self 
     where I: IntoIterator<Item = T> 
    { 
     let mut iter = iter.into_iter(); 
     let (lower, _) = iter.size_hint(); 
     let ans = Self::with_capacity(lower); 
     while let Some(x) = iter.next() { 
      ans.push(x); 
     } 
     ans 
    } 
} 

編譯器韓元不讓我:

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 

我想我理解錯誤信息;它會阻止我編寫與標準庫可能的未來更改不兼容的代碼。

解決此錯誤的唯一方法似乎是針對實施Buffer的每種類型單獨實施FromIterator。這將涉及多次複製完全相同的代碼。有沒有一種方法可以在所有Buffer類型之間共享相同的實現?

+1

*將來可能會更改爲標準庫* - 不僅僅是標準庫,還有您的代碼將來可能鏈接(或鏈接到)的任何庫。 – Shepmaster

回答

0

對於任意類型,不能從另一個箱子實現特徵,只能從箱子類型中實現特徵。但是,您可以實施移動到功能,減少重複的代碼量:

fn buffer_from_iter<I, B>(iter: I) -> B 
    where I: IntoIterator<Item = B::Item>, 
      B: Buffer 
{ 
    let mut iter = iter.into_iter(); 
    let (lower, _) = iter.size_hint(); 
    let mut ans = B::with_capacity(lower); 
    while let Some(x) = iter.next() { 
     ans.push(x); 
    } 
    ans 
} 

struct S1; 
impl Buffer for S1 { 
    type Item = i32; 
    fn with_capacity(c: usize) -> Self { unimplemented!() } 
    fn push(&mut self, item: Self::Item) { unimplemented!() } 
} 

impl std::iter::FromIterator<<S1 as Buffer>::Item> for S1 { 
    fn from_iter<I>(iter: I) -> Self 
     where I: IntoIterator<Item = <S1 as Buffer>::Item> 
    { 
     buffer_from_iter(iter) 
    } 
} 

FromIterator此實現可包裹成一個宏,以進一步減少代碼的重複。

+0

更好的是,你的'buffer_from_iter'可以是'Buffer :: from_iter',以便去除一個類型變量和大量的「as Buffer」子句。我自己做了很多工作。 :-(使用宏的想法很好,我不介意偶爾寫「buffer_from_iter!(MyType)」,我會接受一個答案,說明如何做到這一點。 – apt1002

+0

這個怎麼樣? !) https://gist.github.com/apt1002/1b5139f0e0d4e700b5732e0ae44fe3fb – apt1002