![](/img/trans.png)
[英]How do I write generic code that accepts either a trait or a smart pointer to the trait (Box, Rc, etc)?
[英]How do I write a function in Rust that accepts any iterator whose Item fulfills a trait?
这是我想要达到的目标的人为示例:
trait Double {
fn get(&self) -> i32;
}
impl Double for i32 {
fn get(&self) -> i32 { self * 2 }
}
fn foo<'a, I: Iterator<Item = &'a Double>>(is: I) {
for i in is {
println!("{}", i.get());
}
}
fn main() {
let is = vec![1, 2, 3, 4];
foo(is.into_iter());
}
错误在这里显示为“期望的积分变量,找到&Double
”。
我到处都在寻找麻烦,因为到处都在谈论迭代器是特质。 我要做什么甚至有可能吗?
是的,有可能。 您需要使用where
子句来指定关联类型I::Item
的绑定。
fn foo<I>(is: I)
where I: Iterator,
I::Item: Double,
{
for i in is {
println!("{}", i.get());
}
}
(我还将I: Iterator
绑定到where
子句,以使所有边界保持在一起。)
绑定的Iterator<Item = &'a Double>>
表示您想要一个迭代器,该迭代器产生的类型&Double
完全相同,该类型表示特性Double
的特性对象。 但是,您需要一个迭代器,该迭代器可以产生实现特征Double
任何类型。 这听起来很相似,因此令人困惑,但这全是关于动态与静态分派。 您应该阅读有关特质对象的Rust书一章,以了解到底发生了什么。
但快速总结:写作之间有区别
fn foo<T: MyTrait>(t: &T) {}
和
fn foo(t: &MyTrait) {}
您编写了与后者等效的代码,但实际上要使用前者。
那么,您如何用代码表达您的意图? 一种可能是引入另一种类型参数!
fn foo<'a, T, I>(is: I)
where T: Double,
I: Iterator<Item = &'a T>,
{
for i in is {
println!("{}", i.get());
}
}
但是您也可以绑定迭代器的关联类型(请参见FrancisGagné的答案 ):
fn foo<I>(is: I)
where I: Iterator,
I::Item: Double,
{ ... }
但是,这两个版本略有不同,因为一个版本接受对实现Double
类型的引用的迭代器,而另一个版本对直接实现Double
类型的迭代进行迭代。 只需使用最适合您的方法或使用AsRef
特征概括这两件事。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.