2016-11-03 3 views
1

Я хочу вектор для элементов, которые содержат черту, такую ​​как Eq, и мне нужны гетерогенные векторы. Например:Возможно ли иметь гетерогенный вектор типов, которые реализуют Eq?

let mut x: Vec<Eq> = Vec::new(); 

x.push(1); 
x.push("hello") 

Я получаю сообщение об ошибке, которое говорит, что Eq не может быть превращена в объект:

error[E0038]: the trait `std::cmp::Eq` cannot be made into an object 
--> src/main.rs:2:20 
    | 
2 |  let mut x: Vec<Eq> = Vec::new(); 
    |     ^^ the trait `std::cmp::Eq` cannot be made into an object 
    | 
    = note: the trait cannot use `Self` as a type parameter in the supertrait listing 

Можно ли получить список указателей на вещи, которые я могу сравнить, независимо от их типы?

+1

Если вы счастливы использовать 'Any' черту вместо' Eq' специально, 'VEC > 'works ([linkground link] (https://play.rust-lang.org/?gist=22fcc82ccea3f0b0aa0f3528f23d35a6&version=stable&backtrace=0)). – Aurora0001

+0

Спасибо, но мне действительно нужно иметь возможность сравнивать вещи в векторе. В частности, большая проблема заключается в том, что я хотел бы иметь HashMap с гетерогенными ключами. – FCo

ответ

6

Возможно ли иметь список указателей на вещи, которые я могу сравнить независимо от их типов?

Это не имеет смысла. Как вы сравниваете String и File или Socket и GuiWindowFontFamily?

В коде есть некоторые второстепенные проблемы, а именно, что ему не хватает какой-либо косвенности для этого признака. См. What is the best way to create a heterogeneous collection of objects? для хорошего обзора того, как сделать гетерогенный вектор, если он не защищает объект.

Обсуждение объект безопасности, there's a great blog series on the subject, который охватывает детали конкретной ошибки, которую вы получаете.

Итак, что мы можем сделать? Для начала, мы можем быть более конкретными:

let mut x: Vec<Box<PartialEq<u8>>> = Vec::new(); 

Это работает, потому что мы говорим, что все в векторе можно сравнить с u8, и не открытым составом бесконечного числа возможностей, что каждый может быть сравнен к.

Вы также можете реализовать некоторые черты, которые диктует, как все должно быть сравнены, а затем использовать это:

trait Silly { 
    fn silly(&self) -> usize; 
} 

impl Silly for u8 { 
    fn silly(&self) -> usize { *self as usize } 
} 

impl Silly for bool { 
    fn silly(&self) -> usize { 1 } 
} 

fn main() { 
    let mut x: Vec<Box<Silly>> = Vec::new(); 
} 
+0

Спасибо. Сравнение вещей различного типа очень просто, значения разных типов всегда разные, однако значения одного и того же типа могут быть равны. В моем случае то, что я пытаюсь реализовать, является n-арным деревом, где каждый уровень имеет разные типы ключей, поэтому мне нужно, чтобы общий тип типа был несколько общим, и мне полностью нужны Eq и Hash. – FCo

+2

@FCo Какие ключевые типы мы имеем в виду? Разве вы не можете их обернуть вокруг перечисления? –

+2

Перечисление - отличное решение, ИМО. Тогда пользователь структуры данных должен реализовать «Eq», если это необходимо. – Shepmaster