私は値への参照があり、ラッパーの値をラップする構造体への参照で置き換えたいと考えています。&Wrapperで置換&タイプ<Type>
例:
struct Wrapper<T>(T);
let num = 123;
let x: &i32 = #
let wrapped: &Wrapper<i32> = .. // some conversion
これは可能ですか? (安全な溶液が望ましいですが、必要ではありません)
私は値への参照があり、ラッパーの値をラップする構造体への参照で置き換えたいと考えています。&Wrapperで置換&タイプ<Type>
例:
struct Wrapper<T>(T);
let num = 123;
let x: &i32 = #
let wrapped: &Wrapper<i32> = .. // some conversion
これは可能ですか? (安全な溶液が望ましいですが、必要ではありません)
:
C++から来るlet wrapped: &Wrapper<i32> = &Wrapper(*x); // type annotation optional
我々はへの参照を取るので、あなたは、これは夢中になって安全ではないと思うかもしれません一時的なもの(左側の式)。しかし、このような状況では、Rustはこの一時的な式の結果をスタックに保存するだけです。上記のコードは、
let hidden = Wrapper(*x);
let wrapped: &Wrapper = &hidden;
と同等ですが、このリファレンスを返すときには問題が発生します。例:
fn wrap<T>(t: &T) -> &Wrapped<T> {
&Wrapped(*t)
}
ここでは2つの問題があります。最初に、t
から移動することはできません(i32
はCopy
なので、上記のコードでのみ動作しました)。次に、ローカル変数(hidden
は私たちのために作成されたもの)。
これを解決するには、unsafe
機能std::mem::transmute()
を使用することができます。これは、どんな型も他の型として解釈します。
お待ちください! unsafe {}
は「コンパイラ、これを信頼してください!」という意味ですが、自分自身を信頼する必要がありますか?プログラマは、Wrapped<T>
とT
のデータレイアウトが全く同じであることを保証する必要があります。そうですか?
これはおそらくほとんどのプラットフォームで当てはまりますが、私たちがこれを保証できるかどうかは非常に疑問です!構造体(とユニット構造体)のデータレイアウトに関しては、Rustは多くのことを約束していないようです。フィールドを並べ替えることができ(この場合重要ではない)、パディングを追加することがあります。 repr(Rust) chapter of the Rustonomiconにこれに関する詳細があります。
を要約すると:wrap()
のような機能がを安全に実装することができません。結果として、そのような機能を含むAPIは避けなければなりません。
あなたはコンバージョンを必要としません。あなたは、次のようにこれを達成することができます:あなたの例のコードを動作させるのは簡単だ
#[derive(Debug)]
struct Wrapper(i32);
let num = 123; // the value
let x = # // the reference to the value
let wrapped: Wrapper = Wrapper(*x); // now you can refer to &wrapped
println!("{:?}", wrapped);
質問は、どのような条件の下で、「ラップ」関数がいつ発音するのですか?当社には、文書による保証はありません。 – bluss
@bluss私はその問題に関するさらなる情報を追加しました。それは実際には危険であり、使用されるべきではないように思われるので、正確なコードも削除しました。私はSOの答えで '不安全な 'ソリューションを提供して申し訳ありません。私は通常それをしませんが、10分後にこのような答えを書いていました^ _^ –
@bluss私はいくつかのアプリケーションでメモリレイアウトに関するいくつかの仮定をしていたと思います。'transmute((u32、u32)):: u64'は'(、) 'のレイアウトについて危険な仮定をします。このようなこと(レイアウト保証を強制する)が将来のRustでどのように解決されるのかを追跡する問題はありますか? –