Расширение векдека для ограничения размера

#collections #rust #extends

#Коллекции #Ржавчина #расширяет

Вопрос:

Я хочу реализовать VecDeque с максимальным ограничением размера. У меня есть две стратегии, но я не могу выполнить ни одну.

Первый подход: наследование по составу.

Я создал новую структуру:

 pub struct LimVecDeque<T> {                                                                                                    
     deque: VecDeque<T>,                                                 
     limit: usize,                                                       
}

  

И создайте новую функцию push:

 impl<T> LimVecDeque<T> {
  ...

  pub fn push (amp;self, elem: T) {
    self.deque.push_back(elem);
    if self.limit < self.deque.len() {
      self.deque.pop_front();
    }
  }

  ...
}
  

Это работает, но по мере роста моей программы мне требуется добавить функциональность в мою структуру LimVecDeque. Большинство из них является копией исходного VecDeque:

 pub fn len(amp;self) -> usize {
  self.deque.len()
}
  

У меня больше проблем с экспортом VecDeque ::iter(). У меня были проблемы с типами и итераторами (я пока не очень хорошо разбираюсь в итераторах).
Этот подход заставляет меня клонировать / экспортировать каждую функцию в VecDeque в LimVecDeque. Много работы!

Второй подход: создайте новый признак и реализуйте для VecDeque:

 trait Limited {
  type Elem;

  pub fn push_bounded(amp;self, limit: usize, elem: Elem);
}
  

и позже реализовать признак с помощью VecDeque.

Но я должен передавать limit значение при каждой вставке. Как можно передать предельное значение один раз?

В общем, каков простой способ добавить функциональность в структуру из std (без потери / скрытия текущих)?

Ответ №1:

Как указано в ответе edkeveked, существует доступный crate ( BoundedVecDequeue ) , который реализует именно тот случай, который вы пытаетесь реализовать.

Если вы посмотрите на реализацию BoundedVecDequeue , вы увидите, что она использует первый шаблон, который вы описываете: для создания методов-оболочек, где необходимо изменить поведение обернутого типа, и для делегирования вызовов методов, где это не так.

Как вы указываете, это может привести к большому количеству шаблонов. Чтобы уменьшить объем работы, вы можете попробовать delegate crate, который добавляет макрос, который выполняет делегирование за вас:

 use delegate::delegate;

impl<T> LimVecDeque<T> {
    delegate! {
        to self.inner {

            pub fn len(amp;self) -> usize;
            pub fn truncate(amp;mut self, new_len: usize);
            pub fn as_mut_slices(amp;mut self) -> (amp;mut [T], amp;mut [T]);
            // etc
        }
    }

    // ...

}
  

Предостережение: я сам еще не использовал этот ящик, поэтому не могу ручаться за его качество.

Ответ №2:

BoundedVecDeque делает именно это

 use ::bounded_vec_deque::BoundedVecDeque;

fn main() {
    let mut a = BoundedVecDeque::new(2);
    a.push_front(2);
    a.push_front(3);
    a.push_front(4);
    println!("{:?}", a); //4, 3
}