2016-02-02 61 views
3

我有以下簽名的函數:傳遞切片作爲IntoIterator

pub fn history<'a, I: IntoIterator<Item = &'a str>>(&self, _: I) 

後來,我有一個字段一個struct稱爲main這是一個盒裝關閉。

main: box |args: &[&str], shell: &mut Shell| { 
    shell.history.history(args); 
}, 

的重要組成部分,是我打電話我發現簽名與&[&str]作爲參數的函數。我得到以下編譯錯誤:

src/main.rs:281:47: 281:54 error: type mismatch resolving `<&[&str] as core::iter::IntoIterator>::Item == &str`: 
expected &-ptr, 
    found str [E0271] 
src/main.rs:281   shell.history.history(args); 

因此很明顯,&[&str]不作爲IntoIterator工作。我試過shell.history.history(args.into_iter());,並得到了類似的錯誤消息。

奇怪的是,shell.history.history(args.iter().map(|s|*s));確實有效。這看起來似乎是正確的解決方案。

回答

3

讓我們來看看how IntoIterator is implemented for slices

impl<'a, T> IntoIterator for &'a [T] 
    type Item = &'a T 
    type IntoIter = Iter<'a, T> 
    fn into_iter(self) -> Iter<'a, T> 

注意Item被定義爲參考T,其中T是在切片中的項目類型。由於您有&str的一部分,這意味着Item&&str

您可以使用.map(|s| *s)來嘗試取消引用外部引用並生成&str的迭代器。

另一種解決方案是推廣您的history函數以接受I: IntoIterator<Item = &'a str>I: IntoIterator<Item = &'b &'a str>。爲了做到這一點,我們需要一個&'a str&'b &'a str實現的特徵。我們可以使用AsRef<str>這個(感謝弗拉基米爾Matveev指出這一點):

pub fn history<I: IntoIterator>(_: I) 
    where I::Item: AsRef<str> 
{ 
    for s in i { 
     println!("{}", s.as_ref()); 
    } 
} 

fn main() { 
    history(&["s"]); 
} 
+0

所以是地圖實際上是一個「好」的解決方案?這似乎是一個迂迴的方法。 – skyler

+0

查看我的編輯另一種解決方案。 –

+1

@FrancisGagné不能'AsRef '被用來代替自定義'IntoStrSlice'? –