Подскажите, как заимствовать поле, минуя заимствование структуры? Нужно реализовать Iterator по

ссылкам на значения заимствованной итератором коллекции. Но сигнатура next() не позволяет использовать (&'a mut self)->'a. Для индексируемых по usize коллекций компилятор успокаивается на отправке &collection[i], но если условный collection имеет лишь свой .iter() - возникает заимствование от self, которое мне не нужно.
Задача - итерироваться по ссылкам на элементы коллекции, и при успешной обработке выбрасывать элемент (эдакий 'graceful' .drain()). Использую сейчас вариант с unsafe, который рекомендуют при удалении из set элемента, используя его же в качестве ключа, но хотелось бы без unsafe

struct IdHashDeleteAfterUseIterator<'a, Id> where Id: Eq + Hash {
set: &'a mut HashSet<Id>,
first_done: bool,
}
impl<'a, Id> IdHashDeleteAfterUseIterator<'a, Id> where Id: Eq + Hash {
fn new (set: &'a mut HashSet<Id>) -> IdHashDeleteAfterUseIterator<'a, Id> {
IdHashDeleteAfterUseIterator {set, first_done: false}
}
}
impl<'a, Id> Iterator for IdHashDeleteAfterUseIterator<'a, Id>
where Id: Eq + Hash {
type Item = &'a Id;
fn next(&mut self) -> Option<Self::Item> {
if self.first_done {
if let Some(value_as_key) = self.set.iter().next() {
// https://github.com/rust-lang/rust/issues/27804#issuecomment-406269067
let key_ref = unsafe{&*(value_as_key as *const _)};
self.set.remove(key_ref);
}
}
self.first_done = true;
//let opt = self.set.iter().next(); // error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
//opt
match self.set.iter().next() {
None => None,
Some(v) => {
// зато работает
let myref = unsafe{&*(v as *const _)};
Some(myref)
}
}
}
}
Спасибо

5 ответов

8 просмотров

Стандартный трейт Iterator для такого не подходит. Возвращаемая им ссылка должна быть валидна на протяжении всего времени жизни итератора. Здесь ссылка инвалидируется, что дает возможность сделать UB в safe коде. Например: let a = iter.next(); let _ = iter.next(); a.something();

makaleks-Maksimov Автор вопроса

Так ведь в моём случае эта ссылка и будет валидна всю жизнь итератора, и даже дольше, ведь коллекция по ссылке живёт дольше самой ссылки по-определению. С чего бы возвращаемой ссылке инвалидироваться? Пример с a.something() не ведёт к ub, ведь 1. Итератор до сих пор жив 2. Для моего исходника, даже после drop итератора, set, заимствованный итератором, останется жив Можно подробнее?

makaleks Maksimov
Так ведь в моём случае эта ссылка и будет валидна ...

self.set.remove(key_ref); удаляет элемент, все ссылки на него, в том числе a из моего примера становятся невалидными.

makaleks-Maksimov Автор вопроса

Дошло, спасибо У меня по логике есть гарантия неиспользования элемента за пределами текущей итерации Выходит, следует использовать while let Some(v) = my_next(&mut my_id_hash_delete_after_use_iterator) { … } Где fn my_next<‘a>(set: MyIdHashDeteAfterUseIterator) -> Option<&’a Id> { … } Или существует паттерн получше?

makaleks Maksimov
Дошло, спасибо У меня по логике есть гарантия неис...

Дрейнить и вставлять неиспользованные элементы обратно. Использовать другую структуру данных, а не HashSet

Похожие вопросы

Обсуждают сегодня

Всем привет. Ребята, подскажите, пожалуйста. у ботов есть ограничение на отправку сообщений - 30 сообщений в секунду, эти ограничения накладываются на все сообщения? или на со...
Artem Stormageddon
4
Блин, ребята, сори за тупые вопросы. А можно ли как-то открыть вебапку по нажатию на кнопку в меню(которое появляется слева, команды)?
Artem Stormageddon
3
Ребята, всем привет. Подскажите, пожалуйста, можно ли как-то через бота понять, что этого бота добавили в группу\канал и выдали ему права администратора?
Artem Stormageddon
9
Привет всем! Почему этот код не срабатывает при добавлении или удалении пользователя из чата? bot.on('chat_member', async (ctx) => { console.log(ctx); }) bot.launch({allo...
Alexander
7
Всем привет. Не понимаю, в чём тут шутка юмора. Убирается только разрешение на send_messages. А send_media_messages остаётся. Как сделать, чтобы оба убирались? await b...
Alexander
2
Есть тут кто занимается разработкой серваков майна? Или знакомые
meow *
3
'frakturBold' => ['𝖆', '𝖇', '𝖈', '𝖉', '𝖊', '𝖋', '𝖌', '𝖍', '𝖎', '𝖏', '𝖐', '𝖑', '𝖒', '𝖓', '𝖔', '𝖕', '𝖖', '𝖗', '𝖘', '𝖙', '𝖚', '𝖛', '𝖜', '𝖝', '𝖞', '𝖟', '𝕬', '𝕭', '𝕮', '𝕯'...
Roma
4
Есть ли лимиты на кол-во вебхук по домену? Стоит в данный момент 900+ ботов и бывает бот перестает отвечать (не приходят вебхуки) 🐒 Помогает только перезапуск
ᅠ [ Кому не ответил, дублируйте ]
11
а что делать если тебя убивают на картах?
Yarik yarik kyda ti lezesh
43
Товарищи, здравствуйте Подскажите, пожалуйста, может кто-нибудь сталкивался с такой задачей Через вебапку можно сканировать qr-код, а есть ли возможность считывать nfc?
Artem Stormageddon
8
Карта сайта