非コピー型で大きな固定サイズの配列を初期化する 質問する

非コピー型で大きな固定サイズの配列を初期化する 質問する

Option<Box<Thing>>ある種の の のような、null 可能でコピー不可能な型の固定サイズの配列を初期化しようとしていますThing。 余分な間接参照なしで、そのうちの 2 つを構造体にパックしたいと思います。 次のように記述します。

let array: [Option<Box<Thing>>; SIZE] = [None; SIZE];

しかし、構文ではが を実装する[e; n]必要があるため、動作しません。もちろん、 を に拡張することもできますが、 が大きい場合は扱いにくくなります。 の不自然なエンコードなしでマクロを使用してこれを行うことはできないと思います。これを行う良い方法はありますか?eCopySIZE NoneSIZESIZE

はい、 を使えば簡単ですunsafe。 を使わずにこれを行う方法はありますかunsafe?

ベストアンサー1

Rust 1.79 (2024 年 6 月にリリース予定) では、これを簡単に行うには、インライン const を使用します。

struct Thing;

fn main() {
    const SIZE: usize = 100;
    let _array: [Option<Box<Thing>>; SIZE] = [const {None}; SIZE];
}

遊び場

これは変数の初期化にも機能しますstatic

Rust 1.63(2022年8月リリース)では、以前投稿された回答よりもクリーンな代替案が以下を使用して可能になりました。std::array::from_fn():

const SIZE: usize = 100;
let array: [Option<Box<Thing>>; SIZE] = std::array::from_fn(|_| None);

遊び場

1.63 より前のバージョンの Rust をサポートする必要がある場合、または を初期化する必要がある場合はstatic、中間初期化子を使用する別の方法がconstRust 1.38 (2019 年 9 月リリース) 以降で機能します。

const SIZE: usize = 100;
const INIT: Option<Box<Thing>> = None; // helper
// also works with static array
let array: [Option<Box<Thing>>; SIZE] = [INIT; SIZE]; 

遊び場

最初のアプローチと最後のアプローチには、配列項目がコンパイル時に評価できる表現 (定数、列挙型バリアント、空の Vec または String、またはそれらで構成されるプリミティブ コンテナー (列挙型、タプル)) を持つ必要があるという制限があります。Noneまたは数値のタプルは機能しますが、空でないVecまたははString機能しません。このarray::from_fn()アプローチにはそのような制限はありません。

Box上記の例はすべて、 ;の有無にかかわらず機能します。を使用するのBoxは、質問で ; が使用されているためです。すべて、任意のサイズの配列で機能します。

おすすめ記事