Ответ 1
Вы можете использовать черту Default
для инициализации массива значениями по умолчанию:
let array: [Option<Box<Thing>>; SIZE] = Default::default();
Смотрите эту площадку для рабочего примера.
Я пытаюсь инициализировать массив фиксированного размера некоторого типа NULL, не скопируемого типа, как Option<Box<Thing>>
для некоторого Thing
. Id нравится упаковывать два из них в структуру без какого-либо дополнительного обращения. Id нравится писать что-то вроде этого:
let array: [Option<Box<Thing>>; SIZE] = [None; SIZE];
Но это не работает, потому что синтаксис [e; n]
требует, чтобы e
реализовал Copy
. Конечно, я мог бы расширить его на SIZE
None
s, но это может быть громоздким, когда SIZE
велико. Я не верю, что это можно сделать с помощью макроса без неестественного кодирования SIZE
. Есть ли хороший способ сделать это?
Да, это легко с unsafe
; есть ли способ сделать это без unsafe
?
Вы можете использовать черту Default
для инициализации массива значениями по умолчанию:
let array: [Option<Box<Thing>>; SIZE] = Default::default();
Смотрите эту площадку для рабочего примера.
Я копирую ответ chris-morgan и адаптируя его для лучшего ответа на вопрос, чтобы следовать рекомендации dbupp downthread, и соответствовать последним синтаксическим изменениям:
use std::mem;
use std::ptr;
#[derive(Debug)]
struct Thing {
number: usize,
}
macro_rules! make_array {
($n:expr, $constructor:expr) => {{
let mut items: [_; $n] = mem::uninitialized();
for (i, place) in items.iter_mut().enumerate() {
ptr::write(place, $constructor(i));
}
items
}}
}
const SIZE: usize = 50;
fn main() {
let items = unsafe { make_array!(SIZE, |i| Box::new(Some(Thing { number: i }))) };
println!("{:?}", &items[..]);
}
Обратите внимание на необходимость использования unsafe
здесь: проблема в том, что если функция конструктора panic!
s, это приведет к поведению undefined.
Это простой ответ: просто наберите все значения:
struct Thing;
const SIZE: usize = 5;
fn main() {
let array: [Option<Box<Thing>>; SIZE] = [None, None, None, None, None];
}
Вы также можете использовать скрипт сборки, чтобы сгенерировать этот код для вас.