我试图在参数化类型上实现一些操作(特别是Vec<T>
之上的一些常见&#34;堆栈&#34;操作。但我不确定如何这是有效的,所以这里是我目前正在努力解决的问题的简化版本:
trait Stack<T> {
fn top(&self) -> Option<T>;
}
impl Stack for Vec<T> {
fn top<T>(&self) -> Option<T> {
match self.len() {
0 => None,
n => Some(self[n-1])
}
}
}
fn main() {
let mut stack: Vec<f64> = Vec::new();
stack.push(1324.4);
println!("{}", stack.top());
}
以上错误无法编译(每晚生锈):
test.rs:6:20: 6:21 error: use of undeclared type name `T`
test.rs:6 impl Stack for Vec<T> {
^
error: aborting due to previous error
答案 0 :(得分:2)
这应该有效:
impl<T> Stack<T> for Vec<T> {
fn top(&self) -> Option<T> {
match self.len() {
0 => None,
n => Some(self[n-1])
}
}
}
您需要通知编译器有关实现中相关的Stack
的类型参数。
但这还不够:修复此错误会导致main
函数出现问题,特别是println!
的参数类型错误:
fn main() {
let mut stack: Vec<f64> = Vec::new();
stack.push(42.0);
match stack.pop() {
None => println!("empty stack"),
Some(n) => println!("top: {}", n)
};
}
但是,此修复反过来表明top
方法没有为该代码打字。解决错误的一种方法:
trait Stack<T> {
fn top(&self) -> Option<&T>;
}
impl<T> Stack<T> for Vec<T> {
fn top(&self) -> Option<&T> {
match self.len() {
0 => None,
n => Some(&self[n-1])
}
}
}
编辑:
正如@sellibitze在评论中解释的那样,它不起作用的原因是,从Stack
的原始定义来看,编译器无法知道类型{的值{1}}可复制或至少可克隆 - 即。 T
支持Copy
或Clone
特征,因此无法复制值(在C ++用语中按值返回)。使用引用解决了问题,因为对T
的引用是可复制的
而不是匹配T
的返回值,我可以使用top
在Option<T>
实现它时支持Show
特征的事实,恰好是T
的真实情况。这意味着我可以在f64
宏的调用中简单地用{}
格式化程序替换{:?}
,并保持原始println!
函数的其余部分不受影响。
例如:
main
答案 1 :(得分:1)
如果您想支持返回值而不是引用,则有两种可能的实现方式。请注意,您不能同时拥有。在大多数情况下,您会看到Clone
绑定的那个,因为Copy
的任何类型都应该实现Clone
:
trait Stack<T> {
fn top(&self) -> Option<T>;
}
// We have values where we duplicate by copying bits naïvely
impl<T> Stack<T> for Vec<T>
where T: Copy
{
fn top(&self) -> Option<T> {
self.last().map(|v| *v)
}
}
// We have values where we can duplicate them,
// but it might take a function call to do so
impl<T> Stack<T> for Vec<T>
where T: Clone
{
fn top(&self) -> Option<T> {
self.last().map(|v| v.clone())
}
}
fn main() {
let stack = vec![1324.4f64];
println!("{:?}", stack.top());
}