T
должен быть конкретным типом, а не чертой. Я могу подумать о том, что вам ближе то, что вы ищете:
trait Fnord {
fn do_it(&self) -> i32;
}
impl Fnord for i32 {
fn do_it(&self) -> i32 {
*self
}
}
impl<'a> From<&'a i32> for &'a dyn Fnord {
fn from(i: &'a i32) -> Self {
i as _
}
}
fn iter_as<'a, T, TObj>(objs: &'a [T]) -> impl Iterator<Item = TObj> + 'a
where
TObj: 'a,
TObj: From<&'a T>,
{
objs.iter().map(|o| o.into())
}
fn main() {
let objs: Vec<i32> = vec![1, 2, 3];
for s in iter_as::<i32, &dyn Fnord>(&objs) {
println!("{}", s.do_it()); // 1 2 3
}
}
Я не уверен, что вы выбрали идиоматический c Rust способ сделать это: так как вы Зная конкретные типы вашего объекта, вы можете написать его следующим образом:
trait Fnord {
fn do_it(&self) -> i32;
}
impl Fnord for i32 {
fn do_it(&self) -> i32 {
*self
}
}
impl<'a> From<&'a i32> for &'a dyn Fnord {
fn from(i: &'a i32) -> Self {
i as _
}
}
struct YourObject {
v1: Vec<i32>,
v2: Vec<i32>,
}
impl YourObject {
fn iter_as<'a, T>(&'a self) -> impl Iterator<Item = T> + 'a
where
T: From<&'a i32>, // Add the other bounds you need
{
self.v1
.iter()
.map(|o| o.into())
.chain(self.v2.iter().map(|o| o.into()))
}
}
fn main() {
let obj = YourObject {
v1: vec![1, 2],
v2: vec![3],
};
for s in obj.iter_as::<&dyn Fnord>() {
println!("{}", s.do_it()); // 1 2 3
}
}
С помощью макроса:
macro_rules! impl_from_for_dyn_trait {
( $concrete:ty, $trait:path ) => {
impl<'a> From<&'a $concrete> for &'a dyn $trait {
fn from(c: &'a $concrete) -> Self {
c as _
}
}
}
}
impl_from_for_dyn_trait!(i32, Fnord);
можно сократить шаблон реализации
From
.