Могу ли я создать структуру, которая работает как со значениями, так и с заимствованными ссылками на черту?

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

Например, допустим, у меня есть черта Foobar:

trait Foobar {
    fn foobar(&self);
}

Теперь я хочу создать структуру, которая обертывает значения или заимствованные ссылки на эту черту:

struct FoobarWrapper<T: Foobar> {
    wrapped: T,
    extra_stuff: Stuff
}

Здесь я хочу, чтобы FoobarWrapper работал как с Baz, так и с &Baz, учитывая, что impl Foobar for Baz.

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

impl<'a, T: Foobar> Foobar for &'a T  {
    fn foobar(&self) {
        (*self).foobar()
    }
}

Если я не ошибаюсь, здесь любая ссылка на значение, реализующее Foobar, также является разработчиком Foobar. Но так ли вы должны это делать?


person Emil Eriksson    schedule 15.09.2015    source источник


Ответы (1)


Да, ваше решение, вероятно, подходит, если вы можете его поддержать. Iterator делает то же самое с

impl<'a, I> Iterator for &'a mut I where I: Iterator + ?Sized

Вероятно, вам также следует добавить границу ?Sized для гибкости.

person Veedrac    schedule 15.09.2015
comment
?Sized, потому что на самом деле не имеет значения, имеет ли цель размер или нет, если вы берете ее по ссылке? - person Emil Eriksson; 15.09.2015
comment
@EmilEriksson По умолчанию все границы имеют неявный атрибут Sized, который предотвращает использование нестандартных типов. Однако, если вы используете привязку только через косвенное обращение (например, &T или Box<T>), это нежелательно, и ?Sized снимает ограничение. - person Veedrac; 15.09.2015