2015-02-13 2 views
1

Я пытаюсь реализовать несколько операций с параметризованным типом (в частности, некоторые общие операции «стека» поверх Vec<T>. Однако я не уверен, как это работает (пока), так вот урезанная версия того, что я в настоящее время борется с:Использование ошибки неопределенного типа с параметризованным признаком

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

Там же метод, как .TOP уже, называется '.last()', что вы можешь использовать. – bluss

+0

Пожалуйста, не забудьте добавить полезные ответы и пометить ответ как принятый, если он решит вашу проблему! Если ответ не является приемлемым, подумайте о том, чтобы оставить комментарии, объясняющие, почему, или отредактируйте свой вопрос, чтобы сформулировать проблему по-разному. – Shepmaster

ответ

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]) 
     } 
    } 
} 

Edit:

  • , как объяснено @sellibitze в комментариях, почему он не работает является то, что из первоначального определения Stack, компилятор не могли знать, что значения типа T могут быть скопированы или хотя бы клонированы - т.е. что T поддерживает символ Copy или Clone, и, следовательно, значения не могут быть дублированы (возврат по значению на языке C++). Использование ссылки решает проблему, как ссылка на T является копируемыми

  • , а не подогнанным на возвращаемое значение из top, я мог бы использовать тот факт, что Option<T> поддерживает Show черту, когда T реализует его, что происходит, чтобы быть правдой для f64. Это означает, что я мог бы просто заменить {} форматом {:?} в вызове макроса println! и оставить остальную часть оригинальной функции main без изменений.

Например:

fn main(){ 
    let mut stack: Vec<f64> = Vec::new(); 
    stack.push(42.0); 
    println!("top: {:?}", stack.top()) 
} 
+1

Пожалуйста, удалите '' после 'top'. Кроме того, первая реализация, которую вы показываете, не должна работать, потому что она требует «T: Copy». – sellibitze

+0

@sellibitze ах да, я удалил его в своих тестах, но он ускользнул от меня, когда я как-то скопировал его, спасибо! Что касается 'Copy', я не был уверен в причине, почему это не сработало, но с использованием ссылок исправлено это. Я немного скептически относился к тому, что это было оптимальным в случае таких типов, как float и ints. – didierc

+1

«компилятор не мог знать, что значения типа« T »являются копируемыми, т. Е. Что' T' поддерживает «свойство Clone» - обратите внимание, что типы ['Copy'] (http: //doc.rust -lang.org/std/marker/trait.Copy.html)able отличаются от типов, которые являются ['Clone'] (http://doc.rust-lang.org/std/clone/trait.Clone.html) возможность. – Shepmaster

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()); 
} 
+0

Спасибо, я уверен, что ОП оценят ваш вклад, как и я. – didierc

Смежные вопросы