Требовать, чтобы параметр типа был структурой - PullRequest
1 голос
/ 08 января 2020

У меня есть функция, для которой я указал параметр типа T, который я предполагаю в качестве структуры. Затем я собираю итератор T в Ve c.:

pub fn get_matches<T>(
    &self,
) -> Vec< T> 
{
    ...
    some_iter.
        .map(|(k, _v)| T{key:(**k).to_string(), hits: 0})
        .collect()
}

Я получаю эту ошибку :

96 |             .map(|(k, _v)| T{key:(**k).to_string(), hits: 0})
   |                            ^ not a struct, variant or union type

Я пытался иметь тип возвращаемого значения как параметр типа, но я не могу понять, как получить тип элемента Vec и создать его экземпляр. Я просто хочу создать элементы определенной формы (то есть с key: string и hits: usize) и вернуть контейнер того, что ожидает вызывающая сторона.

1 Ответ

5 голосов
/ 08 января 2020

Обобщения Rust отличаются от шаблонов C ++. Существуют веские причины, по которым они различаются, например, улучшенные отчеты об ошибках и более быстрая компиляция.

В C ++ шаблоны (если мы упрощаем) не проверяются на начальной стадии вызова, скорее шаблон продолжает расширяться до это либо успешно, либо выполняется операция, которая не поддерживается указанным типом c.

В Rust типы проверяются немедленно. Спецификация должна быть предоставлена ​​заранее, что означает, что любая ошибка обнаруживается на сайте вызова, в отличие от глубокого расширения шаблона.

В вашем конкретном примере c предполагается, что каждый T должен иметь поля key и hits, но T может быть любым, начиная от примитивных типов до непубличных c структур, которые не имеют полей key или hits.

The Rust способ сделать что-то - объявить черту и использовать ее, чтобы указать, что у типа есть определенная функция конструктора для вас. В этом контексте черта будет абстракцией с нулевой стоимостью из-за полиморфизма stati c.

trait StringConstructable {
    fn new(string: String) -> Self;
}

struct Test {
    key: String,
    hits: usize
}

impl StringConstructable for Test {
    fn new(string: String) -> Self {
        Test {
            key: string,
            hits: 0
        }
    }
}

fn test<T: StringConstructable>() -> T {
    T::new("test".to_string())
}

ссылка на игровую площадку

Или реализовать и потребовать From<String> для вашей T.

struct Test {
    key: String,
    hits: usize
}

impl From<String> for Test {
    fn from(string: String) -> Test {
        Test {
            key: string,
            hits: 0
        }
    }
}

fn test<T: From<String>>() -> T {
    T::from("test".to_string())
}

ссылка на игровую площадку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...