наверняка кому-то встречалась: сделать итератор как drain(), только чтобы удалял элемент не перед началом итерации, а после
                  
                  
                  Почему явно прописанное время жизни ссылки ограничивается временем жизни поля, по которому эта ссылка лежит?
                  
                  
                  use std::collections::HashSet;
                  
                  
                  use std::hash::Hash;
                  
                  
                  
                  
                  
                  struct IdHashDeleteAfterUseIterator<'a, Id> where Id: Eq + Hash {
                  
                  
                      set: &'a mut HashSet<Id>,
                  
                  
                      first_done: bool,
                  
                  
                  }
                  
                  
                  impl<'a, Id: Eq+Hash> Iterator for IdHashDeleteAfterUseIterator<'a, Id> {
                  
                  
                      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
                  
                  
                                  // конечно, я предполагаю, что нет никакого смысла для std обращаться к элементу
                  
                  
                                  // после удаления, но небезинтересно, почему такой сценарий обязан быть unsafe
                  
                  
                                  let key_ref = unsafe{&*(value_as_key as *const _)};
                  
                  
                                  self.set.remove(key_ref);
                  
                  
                              }
                  
                  
                          }
                  
                  
                          self.first_done = true;
                  
                  
                          // эта строчка не компилится
                  
                  
                          self.set.iter().next()
                  
                  
                          // эти строчки компилятся, но может я создаю опасность?
                  
                  
                          //let self_ref: &HashSet<Id> = unsafe{&*(self.set as *const _)};
                  
                  
                          //self_ref.iter().next()
                  
                  
                      }
                  
                  
                  }
                  
                  
                  На medium говорят, что времена жизни в прототипе fn next<'a, 'b>(&'a self) -> Option<&'b Self::Item> сделаны такими, чтобы возвращаемое значение не было ограничено временем жизни итератора, но ошибка компилятора противоположна этому.
                  
                  
                  first, the lifetime cannot outlive the anonymous lifetime defined here
                  
                  
                      self.set.iter().next()
                  
                  
                               ^^^^
                  
                  
                  ...so that reference does not outlive borrowed content
                  
                  
                      fn next (&mut self) -> Option<Self::Item> {
                  
                  
                               ^^^^^^^^^
                  
                  
                  but, the lifetime must be valid for the lifetime `'a` as defined here...
                  
                  
                      self.set.iter().next()
                  
                  
                      ^^^^^^^
                  
                  
                  ...so that the types are compatible
                  
                  
                      impl<'a, Id: Eq+Hash> Iterator for ...
                  
                  
                           ^^
                  
                  
                  К допустимости unsafe я пришёл как к варианту ответа на users.rust-lang, но там же ссылаются на реализацию итератора в too-many-lists без unsafe, и там почему-то таких ошибок нет - причина вероятно в обёртке через Option но мне совсем неясно, с фига ли Option компилятору достаточно, а почти тех же моих времён жизни, просто без обёртки - нет
                  
                  
                  
                  
                  
                  Спасибо
                  
                  
                
рабочий исходник лучше ссылкой на play.rust-lang.org
а если попробовать итератор сделать частью структуры?
Владение полей структуры друг-другом вроде бы тот ещё враг borrow checker'а, плюс это часто просто не нужно (сталкивался и не только я), плюс это кажется опять будет работать только с fn next<'a>(&'a self)->Option<&'a Item>, что противоречит типажу Iterator
Обсуждают сегодня