是否可以将特征作为参数传递给像这样的通用函数?
trait Fnord {
fn do_it(&self) -> i32 { 42 }
}
impl Fnord for i32 {}
fn iter_as<'a, T>(objs: &'a [i32]) -> impl Iterator<Item = & 'a dyn T>
{
objs.iter().map(|o| o as &dyn T)
}
fn main() {
let objs: Vec<i32> = vec![1, 2, 3];
// Calls would look like this
for s in iter_as::<Fnord>(&objs) {
println!("{}", s.do_it());
}
}
这产生了我这些错误:
error[E0404]: expected trait, found type parameter `T`
--> src/lib.rs:7:69
|
7 | fn iter_as<'a, T>(objs: &'a [i32]) -> impl Iterator<Item = & 'a dyn T>
| ^ not a trait
error[E0404]: expected trait, found type parameter `T`
--> src/lib.rs:9:35
|
9 | objs.iter().map(|o| o as &dyn T)
| ^ not a trait
warning: trait objects without an explicit `dyn` are deprecated
--> src/lib.rs:16:24
|
16 | for s in iter_as::<Fnord>(&objs) {
| ^^^^^ help: use `dyn`: `dyn Fnord`
|
= note: `#[warn(bare_trait_objects)]` on by default
也就是说,可以iter_as
接受特征作为通用参数,以便它可以返回该特征的可迭代对象吗?我已经搜索了很多答案,但是到现在为止,我觉得我可能在问错问题了。
背景是这样的。我有一个结构,其中包含几个不同具体类型的向量,所有向量都实现相同的特征。我希望struct的impl具有一个函数,该函数可以将所有存储对象作为其任何共同特征返回可迭代。的iter_as
上面是,(名义)功能的简化版本。也许我只是以一种尴尬的方式来处理生锈问题(例如,也许我想的太多了,就像C ++程序员一样),所以一种替代的惯用方法也很好。
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
}
}
我不确定您是否选择了惯用的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
}
}
该From
实施样板可以减少由于宏:
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);
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句