#rust #traits
#Ржавчина #Трейты
Вопрос:
Предположим, у меня есть признак Tr
, определенный как таковой:
trait Tr {
fn tr(amp;self);
}
У меня есть признак, реализованный для некоторого типа, скажем X
:
struct X;
impl Tr for X {
fn tr(self) {}
}
Теперь я хотел бы impl
Tr
для любого типа, который можно превратить в итератор по ссылкам на реализацию значений Tr
.
Я пробовал это: (игровая площадка)
impl<T: IntoIterator<Item = impl Tr>> Tr for T {
fn tr(amp;self) { self.into_iter().for_each(|value| value.tr()) }
}
Но он не компилируется, потому IntoIterator::into_iter
что принимает self
по ходу, а мой признак получает только ссылку.
При этом я попытался также использовать признак self
по ходу движения и реализовать его для ссылок: (игровая площадка)
struct X;
trait Tr {
fn tr(self);
}
impl Tr for amp;X {
fn tr(self) {}
}
impl<T: IntoIterator<Item = impl Tr>> Tr for T {
fn tr(self) { self.into_iter().for_each(|value| value.tr()) }
}
Это отлично компилируется, но работает только для коллекций, содержащих значения X
. Моя цель состоит в том, чтобы он работал с коллекциями, содержащими ссылки на X
, например: [amp;X]
.
Чтобы решить эту проблему, я реализовал Tr
для двойных ссылок на X
, что работает, но выглядит странно: (игровая площадка)
impl Tr for amp;amp;X {
fn tr(self) {}
}
Это также не позволяет мне напрямую вызывать tr
экземпляры X
, как это было возможно при использовании impl
для одной ссылки: X.tr()
и вместо этого я должен поместить X
хотя бы одну ссылку, чтобы вызвать tr
ее : (amp;X).tr()
. Это, конечно, можно решить, добавив еще impl
один для одной ссылки, но это значительно увеличивает сложность, когда у меня много типов, которые реализуют Tr
.
Вопрос в том, правильно ли это сделать в Rust? Могу ли я каким-либо образом упростить код или вообще избавиться от «взятия self
по ходу»?
Редактировать: в идеале результат должен допускать все следующее:
X.tr();
[amp;X].tr();
vec![amp;X].tr();
(amp;[amp;X]).tr();
(amp;vec![amp;X]).tr();
Комментарии:
1. Это отлично компилируется, но работает только для коллекций, содержащих значения X. Моя цель состоит в том, чтобы он работал с итерациями по ссылкам на X. Хм … это так .
2. @trentcl Возможно, я не слишком четко выразился там. Моя цель — заставить его работать не с итераторами, которые дают ссылки
X
, а с коллекциями, содержащими ссылки, такие какvec![amp;X]
. (что приводит к тому, что итераторы выдают двойные ссылки)