Newtype パターンにおける参照型の変換について。
『Newtype パターン』では、既存の型をラップして新しい型を作る。これにより、汎用的な型の特殊化や、完成済の型の再編集が可能になる。なお、Rust で型 Old
を型 New
に単純にラップするには、struct New(Old);
のように定義する。
Newtype パターンでは、ラップ元の型の参照 &Old
からラップ先の型の参照 &New
への変換が欲しくなる場合がある。つまり、型システム的に区別はしているが、ラップ元とラップ先の内容は元々は同じである事を利用する。
unsafe な機能 std::
が必要になる。これでラップ元の型への参照をラップ先の型への参照として強引に扱う。そして、内容が同じでも最適化の都合などでメモリ構造が変わる可能性があるので、ラップ先の型に属性 #[repr(transparent)]
を指定する事も忘れてはならない。
以下では、from_ref
関数が &i32
を &Newtype
に変換している。
fn main() {
let base = 1;
let newtype = Newtype::from_ref(&base);
assert_eq!(newtype.value(), base);
}
#[repr(transparent)]
pub struct Newtype(i32);
impl Newtype {
pub fn value(&self) -> i32 {
self.0
}
pub fn from_ref(r: &i32) -> &Self {
unsafe { std::mem::transmute(r) }
}
}
参照型のキャストのための専用クレート。参照から参照への変換を提供する RefCast
トレイトとその自動実装により、unsafe コードの記述を肩代わりしてくれる。