2016-11-19 41 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