2016-04-18 2 views
2

У меня есть циклический буфер, как это:Как выразить жизни для Rust итератора для контейнера

struct CircularBuffer<T: Copy> { 
    seqno: usize, 
    data: Vec<T>, 
} 

И я хочу, чтобы создать внешнюю-структуру является итератором. Эта структура будет относиться к внутреннему вектору данных из CircularBuffer, как эти:

struct CircularBufferIterator<'a, T: 'a + Copy> { 
    buffer: &'a CircularBuffer<T>, 
    position: usize, 
    limit: usize, 
} 

Это лучшее, что я мог придумать, что на самом деле компилирует. Можете ли вы предложить лучший способ выразить, что CircularBufferIterator зависит от объекта CircularBuffer?

Какие проблемы у меня есть T: 'a + Copy. Интересно, возможно ли это или имеет смысл сказать, что не тип T, но CircularBuffer<T> - это тот, на который зависит CircularBufferIterator.

Часть, которую я не вижу, почему мне нужно добавить 'a срок службы до T. Разве это не может быть T: Copy, без целой жизни? Другими словами, я не вижу случая, когда T ссылается на CircularBuffer. Это ссылка CircularBuffer, которая переживает CircularBufferIterator.

CircularBuffer и контекст исходит из this blog post.

+0

Непонятно, в чем проблема с представленным решением.'T' должен пережить' 'a', чтобы предотвратить оборванные указатели; 'T' должен быть' Copy', потому что вы определили 'CircularBuffer' как таковой. – Shepmaster

+1

Благодарим вас за помощь в форматировании. Я не уверен, есть ли проблемы. Я просто не совсем понимаю, как это работает. Часть, которую я не вижу, почему мне нужно добавить «время жизни в T. Не может ли быть T: Скопировать, без целой жизни? Другими словами, я не вижу случая, когда T-образ переживает CircularBuffer. Это ссылка CircularBuffer, которая переживает CBIterator. Поэтому я искал более удобный способ выразить именно это. –

ответ

3

почему мне нужно добавить 'a всю жизнь T

Вы не добавляя всю жизнь T; вы говорите, что независимо от того, что выбрано T, оно может только содержать ссылки, что пережить 'a. Если бы это было не так, мы могли бы ссылаться на тип, у которого есть ссылка, которая теперь недействительна. Использование этой недопустимой ссылки приведет к ненадежности памяти; что Руст стремится избежать.


Первоначально я думал, что вы спрашивали, как удалить Copy связанные, так вот все, что я напечатал.

Одним из изменений было бы удалить Copy, связанный с CircularBuffer, но оставив его на реализацию методов. Тогда вам не нужно итератора на всех:

struct CircularBuffer<T> { 
    seqno: usize, 
    data: Vec<T>, 
} 

struct CircularBufferIterator<'a, T: 'a> { 
    buffer: &'a CircularBuffer<T>, 
    position: usize, 
    limit: usize, 
} 

Еще одно изменение было бы полностью отказаться от прямой ссылки на CircularBuffer в целом, и поддерживать прямые итераторы в Vec:

struct CircularBufferIterator<'a, T: 'a> { 
    first: std::slice::Iter<'a, T>, 
    second: Option<std::slice::Iter<'a, T>>, 
} 

Однако, глядя на реализацию Iterator, я вижу, что она возвращает T, а не &T, поэтому вам в конечном итоге нужен тип Copy или Clone. Вы заметите, что стандартная библиотека не требует этого, потому что возвращает ссылку на элемент в коллекции. Если вам не нужна ссылка, вот что такое into_iter или Iterator::cloned.

+0

Это проясняет многое, спасибо вам большое! Мне очень нравится идея среза. Я буду экспериментировать с ним. Я считаю, что это ближе всего к тому, чего я хотел достичь. –

Смежные вопросы