LoginSignup
9
4

More than 5 years have passed since last update.

Rustでもtraitを特殊化したい!

Posted at

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)で変換できるようになったが、釈然としない。。。

参考資料

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4