使用未声明的类型名称错误和参数化特征

时间:2015-02-13 22:32:43

标签: rust traits

我试图在参数化类型上实现一些操作(特别是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

2 个答案:

答案 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支持CopyClone特征,因此无法复制值(在C ++用语中按值返回)。使用引用解决了问题,因为对T的引用是可复制的

  • 而不是匹配T的返回值,我可以使用topOption<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());
}