概要
タイトル通り、ベクタを要素に持つ配列を作りたかったが、エラーに悩んだのでメモ。
rustは配列を宣言すると、初期化することが求められるが、その初期化がうまくいかなかった。
やりたいこと
struct Point{
x: f32,
y: f32,
z: f32,
}
fn main() {
let array: [Vec<Point>; 100] = [vec![]; 100];
// Error : the trait bound `Vec<Point>: Copy` is not satisfied
}
Point
構造体を確保するベクタを要素として、配列に確保したかった。
- 座標情報を持つ
Point
構造体- x, y, zの座標情報を持つ
- 格納するベクタ
Vec<Point>
- 点群データを管理したい -> 要素数が未知のため、ベクタで確保
- そのベクタを要素とする要素数
100
の配列- 座標により、100つの格子分けをしたかった
- 格子別に処理を行う際、配列に確保されていれば便利だと考えた
解決策
1 : Default::default()
を使う
fn main() {
let array: [Vec<Point>; 10] = Default::default();
// これはOK
// let array: [Vec<Point>; 100] = Default::default();
// これはNG (要素数が32を超えるため)
}
手っ取り早く解決するならこれ。
ただし要素数が32
を超えるとNGの模様。
他にはrustのバージョンによって動作しないらしい。
自分の場合、要素数を100
にしたかったため、別の方法を探した。
2 : 要素、サイズを const
で宣言する (非推奨?)
初期化はできるが要素の追加ができないため、ほぼ意味のないコードになっている
fn main() {
const INIT_ELEMENT: Vec<Point> = vec![];
const ARRAY_SIZE: usize = 100;
// 初期化に使用するパラメータをあらかじめ const で宣言
let array: [Vec<Point>; ARRAY_SIZE] = [INIT_ELEMENT; ARRAY_SIZE];
// これでOK
}
要素数に縛られることなく初期化したいならこれ。
配列を初期化する際、要素の型 (ここではVec<Point>
)、要素数 (usize
) をconst
であらかじめ宣言しておき、それを使う。
ただしこちらもバージョンによって動作しないらしい。
追記
const
でvec
を確保しているので、push
ができない。何やってんだこのコード...
3 : unsafe
を使い、初期化する
fn main() {
// 1
const SIZE: usize = 100;
let mut uninit_array: [std::mem::MaybeUninit<Vec<Point>>; SIZE];
// 変数が初期化されないことを宣言する
uninit_array = unsafe{
std::mem::MaybeUninit::uninit().assume_init()
};
// 配列分確保のみをする
// 2
for element in &mut uninit_array{
unsafe{std::ptr::write(element.as_mut_ptr(), vec![])};
// 各要素を vec![] で初期化
}
// 3
let mut array = unsafe{std::mem::transmute::<_, [Vec<Point>; SIZE]>(uninit_array)};
// std::mem::MaybeUninit<Vec<Point>> 型から、Vec<Point> に変換する
}
どうやっても safe Rust
では再現できない気がしたので、 unsafe Rust
で作ってみた。
手順としては、
-
std::mem::MaybeUninit<T>
を使い、配列を初期化なしで宣言する。C で言うint array[10];
みたいなもの - その配列を
for
ループで回し、各要素に初期価値を代入する -
std::mem::transmute
を使い、std::mem::MaybeUninit<T>
を<T>
の配列に変換する
という風に、Cライクに配列を初期化することで対応した。
このようなことでもunsafe
を使わないといけないので、メモリ管理を意識しないといけないと分かった。
参考
https://doc.rust-lang.org/std/default/trait.Default.html
https://doc.rust-lang.org/nightly/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element
https://www.joshmcguigan.com/blog/array-initialization-rust/