2015-07-08 33 views
7

Tôi đang cố tạo một đặc điểm với các hàm trả về trình lặp.đặc điểm với các hàm trả về trình lặp vòng

ví dụ đơn giản của tôi trông như thế này:

pub trait TraitA { 
    fn things(&self) -> Iterator<Item=&u8>; 
} 

fn foo<A: TraitA>(a: &A) { 
    for x in a.things() { } 
} 

nào không làm việc vì loại kích thước Iterator không biết đến lúc biên dịch.

+0

Nếu sử dụng một loại liên quan như đề xuất trong các câu trả lời dưới đây là không phù hợp (có thể không), sau đó bạn có thể trở lại một 'Hộp > 'để thay thế. Nhưng điều này sẽ đòi hỏi một sự phân bổ đống! – BurntSushi5

Trả lời

7

libstd Rust có một thực hiện điều này, các đặc điểm IntoIterator .

/// Conversion into an `Iterator` 
pub trait IntoIterator { 
    /// The type of the elements being iterated 
    type Item; 

    /// A container for iterating over elements of type `Item` 
    type IntoIter: Iterator<Item=Self::Item>; 

    /// Consumes `Self` and returns an iterator over it 
    fn into_iter(self) -> Self::IntoIter; 
} 

Các đặc điểm có by-value (self) xây dựng đặc biệt này một cách chính xác để có thể thể hiện cả hai “vào iterator” và “mượn iterator” ngữ nghĩa.

Được chứng minh bằng cách thực hiện IntoIterator của HashMap. (Họ sử dụng cấu trúc lặp của Hashmap IterIntoIter.) Điều thú vị ở đây là đặc điểm được triển khai cho loại &HashMap<K, V, S> để biểu thị “trình vòng lặp mượn”.

impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> 
    where K: Eq + Hash, S: HashState 
{ 
    type Item = (&'a K, &'a V); 
    type IntoIter = Iter<'a, K, V>; 

    fn into_iter(self) -> Iter<'a, K, V> { 
     self.iter() 
    } 
} 

impl<K, V, S> IntoIterator for HashMap<K, V, S> 
    where K: Eq + Hash, S: HashState 
{ 
    type Item = (K, V); 
    type IntoIter = IntoIter<K, V>; 

    /// Creates a consuming iterator, that is, one that moves each key-value 
    /// pair out of the map in arbitrary order. The map cannot be used after 
    /// calling this. 
    fn into_iter(self) -> IntoIter<K, V> { 
     /* ... */ 
    } 
} 
1

Dựa trên question khác, tôi nghĩ rằng cách tốt nhất để làm điều đó sẽ được xác định Iterator như một loại đặc điểm, như vậy:

pub trait TraitA<'a> { 
    type I1: Iterator<Item=u8>; 
    type I2: Iterator<Item=&'a u8>; 

    fn iter_i1(&self) -> Self::I1; 
    fn iter_i2(&self) -> Self::I2; 
} 

fn foo<'a, A: TraitA<'a>>(a: &A) { 
    for x in a.iter_i1() { } 
    for x in a.iter_i2() { } 
} 
Các vấn đề liên quan