Rustは現在(2017/1/6)のstable(1.14)ではtraitの特殊化をサポートしてないようだ。でもやりたいので遊んでたらできたのでまとめておく。
let a: f64 = 1.0;
let b: f32 = a.into();
そもそものモチベーションはこれがコンパイルできない事だった
trait `f32: std::convert::From<f64>` not satisfied
と怒られる。いや切り捨て以外の選択肢とかないだろと思いつつ、既存のtraitFrom<f64>
を既存の型f32
には実装できないので、新しくtraitを作ることにする。
trait Fromf64 {
fn from_f64(f64) -> Self;
}
これは既存のFrom<f64>
インスタンスにはfrom()
を使ってf32
にはas f32
で変換したい。
impl<A: From<f64>> Fromf64 for A {
fn from_f64(v: f64) -> A {
v.into()
}
}
impl Fromf64 for f32 {
fn from_f64(v: f64) -> f32 {
v as f32
}
}
しかしこれが通らない
error[E0119]: conflicting implementations of trait `Fromf64` for type `f32`:
--> src/main.rs:11:1
|
5 | impl<A: From<f64>> Fromf64 for A {
| - first implementation here
...
11 | impl Fromf64 for f32 {
| ^ conflicting implementation for `f32`
これが通らないのが納得いかないが、通らない以上仕方がない(´・ω・`)
試行錯誤の結果、ダミー型を一つかませるといけることに気付いた
pub trait Fromf64<Dummy> {
fn from_f64(f64) -> Self;
}
impl<A: From<f64>> Fromf64<A> for A {
fn from_f64(v: f64) -> A {
v.into()
}
}
impl Fromf64<()> for f32 {
fn from_f64(v: f64) -> Self {
v as f32
}
}
使うときはこのDummy
を省略できるようにする
let a = f32::from_f64(1.0);
これでA::from_f64(v)
で変換できるようになったが、釈然としない。。。
参考資料
- Tracking issue for specialization (RFC 1210): https://github.com/rust-lang/rust/issues/31844
- How to use specialization features: https://users.rust-lang.org/t/how-to-use-specialization-features/6023