2015-01-28 2 views
0

Итак, я только начинаю изучать немного ржавчины, и я бегу к довольно простой проблеме. У меня есть рекурсивный тип вроде этого:Рекурсивные типы и массивы

struct Tree { 
    root : i32, 
    children : Box<[Option<Tree> ; 100]> 
} 

Позже, когда я пытался инициализировать дерево

hex.rs:30:29: 30:40 error: the trait `core::marker::Copy` is not implemented for the type `Tree` [E0277] 
hex.rs:30   children : Box::new([None; 100]) 
             ^~~~~~~~~~~ 
error: aborting due to previous error 

Итак, я добавил

#[derive(Copy)] 

перед определением структуры, но я получил эта ошибка:

hex.rs:8:10: 8:14 error: the trait `Copy` may not be implemented for this type; field `children` does not implement `Copy` [E0204] 
hex.rs:8 #[derive(Copy)] 
        ^~~~ 
note: in expansion of #[derive] 
hex.rs:8:1: 8:16 note: expansion site 
error: aborting due to previous error 

Я не совсем уверен, куда идти отсюда. Есть ли простой способ получения признаков для рекурсивных типов данных?

+1

Это не просто '[None; 100], что вы не можете писать; '[None, None, None, None, ...]' будет работать нормально. Но семантически я полагаю, что 'Vec ' больше того, чего вы хотите. –

+0

Правильно, я пробовал это, и это сработало, но это не так по многим причинам. Vec работает для того, что мне нужно. – Emil

ответ

1

Проблема в том, что Box не поддерживает Copy. Копия гласит:

Types that can be copied by simply copying bits

Однако Box содержит указатели на память, и эта память не будет скопирована, когда вы просто скопировать биты указателя.

Когда вы строите свой массив, Rust только знает, что вы собираетесь разместить Option. Не существует способа, чтобы перечислить только половину реализации черты.

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

struct Tree { 
    root : i32, 
    children : Vec<Tree> 
} 

Ваш конструктор может использовать Vec::with_capacity:

impl Tree { 
    fn new(root: i32) -> Tree { 
     Tree { root: root, children: Vec::with_capacity(100) } 
    } 
} 
+3

'Box' избыточен, потому что' Vec' уже добавляет слой косвенности. –

+0

Ячейка с фиксированным размером удовлетворит мои потребности намного лучше. – Emil

+0

@ ВладимирМатвеев замечательная точка! В основном из-за моего наивного перевода. :-) – Shepmaster

1

Я боюсь, что вы не сможете использовать статические массивы и рекурсивные типы, как, что без unsafe. Причина в том, что инициализаторы массива требуют, чтобы тип элемента массива был Copy, потому что они инициализируют все элементы с помощью побочных копий исходного элемента, а ваш тип не может быть Copy, потому что он содержит Box, что является единственным безопасным способом, позволяющим рекурсивные типы в Rust (ну, есть также Vec и другие аналогичные контейнеры, но они также нуждаются в распределении кучи).

Если вы не боитесь отчислений, вы можете точно также использовать Vec:

struct Tree { 
    root: i32, 
    children: Vec<Tree> 
} 

Тогда инициализация может выглядеть

Tree { 
    root: 0, 
    children: vec![] 
} 
+0

Но мой начальный элемент - None. Зачем нужен экземпляр «Копировать» для дерева? – Emil

+2

Не имеет значения - ваш тип не является 'Копировать', поэтому' Option 'также не' Копировать'. Я подозреваю, что * возможно * быть возможным вариантам перечисления нуль-аргумента с особым случаем, чтобы они могли использоваться в таких ситуациях, но я думаю, что это редкий случай, поэтому никто не беспокоился. Возможно, когда мы получим родовые литералы, это изменится. –

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