Когда я не должен реализовывать черту для ссылок на разработчиков этой черты?

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

trait Trait {
    fn hello(&self) -> u32;
}

struct Struct(u32);

impl Trait for Struct {
    fn hello(&self) -> u32 { self.0 }
}

fn runner<T: Trait>(t: T) { println!("{}", t.hello()) }

fn main() {
    let s = Struct(42);

    // Works
    runner(s);  

    // Doesn't work
    // runner(&s); 
    // error: the trait `Trait` is not implemented for the type `&Struct`
}

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

impl<'a, T> Trait for &'a T where T: Trait {
    fn hello(&self) -> u32 { (*self).hello() }
}

Часть информации, которую я пропускаю, это когда мне не следует это реализовывать? Спросил другой способ, почему компилятор не реализует это автоматически для меня? Поскольку в настоящее время этого не происходит, я предполагаю, что должны быть случаи, когда такая реализация была бы невыгодной.

2 ответа

Решение

Конкретная черта, которую вы здесь пишете, берет себя только по ссылке, и это единственная причина, по которой это возможно. По этой причине, принимая параметр в runner() по стоимости, вероятно, нежелательно; вместо этого вы должны взять его по ссылке. Это правило может применяться в целом: если возможно реализовать черту для ссылки, то вместо того, чтобы задаться вопросом "должен ли я ее реализовать?", Вам следует задаться вопросом "зачем мне ее реализовывать?" Для тех случаев, когда вы будете ее использовать, вероятно, следует быть изменены, чтобы взять объект по ссылке в первую очередь.

когда я не должен реализовать это? Спросил другой способ, почему компилятор не реализует это автоматически для меня? Поскольку в настоящее время этого не происходит, я предполагаю, что должны быть случаи, когда такая реализация была бы невыгодной.

Например, сразу пришла в голову черта Default.

pub trait Default {
    fn default() -> Self;
}

Я мог бы реализовать это для T, но нет способов автоматически реализовать это для &T.

Другие вопросы по тегам