Как функция может потребовать, чтобы тип реализовал трейт, не удаляя существующую привязку трейта?

Я пытаюсь получить main_func, который возвращает вектор структур типа T с чертой SrObject.

struct TestA {
    value: u8,
}

pub trait SrObject {
    fn myfunc(&mut self);
}
impl SrObject for TestA {
    fn myfunc(&mut self) {
        unimplemented!();
    }
}
impl Default for TestA {
    fn default() -> TestA {
        TestA { value: 3u8 }
    }
}

fn main_func<T: SrObject>(t: T) -> Vec<T> {
    let mut v = Vec::<T>::new();
    for i in 0..10 {
        v.push(T::default());
        //v[i].myfunc();
    }
    return v;
}

это дает:

error[E0599]: no function or associated item named `default` found for type `T` in the current scope
  --> src/main.rs:22:16
   |
22 |         v.push(T::default());
   |                ^^^^^^^^^^ function or associated item not found in `T`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `default`, perhaps you need to implement it:
           candidate #1: `std::default::Default`

Я понимаю, что у меня нет черты Default в фн main_func<T: SrObject>, но как мне добиться этого, не удаляя черту SrObject?


person Slim Shady    schedule 04.05.2018    source источник
comment
Вы задали достаточно вопросов, которые вам следует знать, чтобы включить полное сообщение об ошибке без необходимости редактировать его для вас.   -  person Shepmaster    schedule 04.05.2018


Ответы (1)


Я бы посоветовал вам вернуться и перечитать Язык программирования Rust. Это бесплатная онлайн-книга, созданная сообществом Rust, которая охватывает широкий спектр вещей, которые вам необходимо знать, чтобы стать успешным программистом на Rust.

В этом случае глава о признаках упоминает об границах черты:

Мы можем указать несколько границ свойств для универсального типа, используя +. Если нам нужно иметь возможность использовать форматирование отображения для типа T в функции, а также метод summary, мы можем использовать границы типажа T: Summarizable + Display. Это означает, что T может быть любым типом, реализующим как Summarizable, так и Display.

Для вашего случая:

fn main_func<T: SrObject + Default>() -> Vec<T> {
    (0..10).map(|_| T::default()).collect()
}

Or

fn main_func<T>() -> Vec<T>
where
    T: SrObject + Default,
{
    (0..10).map(|_| T::default()).collect()
}

Другие изменения, чтобы сделать его идиоматичным:

  • Не указывайте тип v при вызове Vec::new; это будет выведено.
  • Не используйте явный return в конце функции.
  • Используйте Iterator::map и Iterator::collect, чтобы преобразовать итератор в коллекцию, а не добавлять элементы рукой.

Смотрите также:

person Shepmaster    schedule 04.05.2018