У меня есть вектор, значения которого определены чертой, и я хотел бы использовать методы, предоставляемые чертой Iterator
для этого вектора.
Вот упрощенный код моего варианта использования:
fn beta<T: Into<i32>>(s: Vec<T>) {
for x in s {
println!("{:?}", x.into());
}
}
fn beta2<U: Into<i32>>(s: Vec<U>) {
for x in s.iter() {
println!("{:?}", x.into());
}
}
Случай А действителен, компилируется и запускается, как ожидалось. Однако Случай B вызовет ошибку времени компиляции:
error[E0282]: type annotations needed
--> src/main.rs:11:26
|
11 | println!("{:?}", x.into());
| ^^^^^^^^ cannot infer type for `T`
Где я должен разместить аннотацию моего типа в этом случае и какова ожидаемая аннотация типа?
Одна из возможностей - сообщить beta2
, что &U
(в отличие от U
) реализует Into<i32>
:
fn beta2<U>(s: Vec<U>)
where
for<'a> &'a U: Into<i32>,
{
for x in s.iter() {
println!("{:?}", x.into());
}
}
Обратите внимание, что Into
принимает self
, а не &self
, т.е. он потребляет свой аргумент. Таким образом, вам нужно будет найти способ конвертировать заимствованный x
в свою стоимость:
fn beta2<U, U2>(s: Vec<U>)
where
U: std::borrow::ToOwned<Owned = U2>,
U2: Into<i32> + std::borrow::Borrow<U>,
{
for x in s.iter() {
println!("{:?}", x.to_owned().into());
}
}
@mattgathu Вы правы. Но обратите внимание, что ошибка возникает не изнутри beta2
, а на сайте вызова. Проблема в том, что x
заимствован (т. Е. Имеет тип &u8
), но Into
ожидает принадлежащую ему стоимость (т. Е. u8
).
&U
(в отличие от U
) - Вы должны объяснить OP, почему эта разница нужна в данном случае.
Какой смысл в этой проблеме, если beta2
все равно потребляет вектор?
@SvenMarnach Я предположил, что «настоящий» код хочет повторить его дважды.
Вместо использования .iter()
более идиоматично передавать вектор как срез: fn beta2<U, U2>(s: &[U])
.
Я не знаю, каков ваш конкретный вариант использования, но я обычно предполагаю, что типы, которые являются Into<u32>
, можно клонировать и их дешево клонировать, поэтому я думаю, что самым простым решением является
fn beta2<U: Clone + Into<i32>>(s: &[U]) {
for x in s.iter().cloned() {
println!("{:?}", x.into());
}
}
Это будет клонировать каждый элемент перед вызовом .into()
для него, который будет использовать клон.
Обратите внимание, что я изменил аргумент s
на срез. Если вы все равно потребляете вектор, беря его по значению, нет никакого вреда в использовании кода из вашего первого примера, поэтому это имеет смысл только в том случае, если вы берете срез по ссылке.
Первый фрагмент выдает ошибку: `` трейт
for<'a> std::convert::From<&'a _>
не реализован для i32``