今日ふとRust 1.20の新機能リストを眺めていたら、Associated constという面白そうな新機能を見つけたのでplaygroundで試してみました。
使い方
こういう使い方ができます。
trait HasConst { const C: f64; } struct A; struct B; impl HasConst for A { const C: f64 = 0f64; } impl HasConst for B { const C: f64 = 1f64; } fn get_const<T: HasConst>(_: T) -> f64 { T::C } fn main() { println!("A {}", get_const(A{})); println!("B {}", get_const(B{})); }
Associated typeと組み合わせることもできます。
trait HasConst { type T; const C: Self::T; } struct A; struct B; impl HasConst for A { type T = f64; const C: f64 = 0f64; } impl HasConst for B { type T = i64; const C: i64 = 1i64; } fn get_const<S: HasConst>(_: S) -> S::T { S::C } fn main() { println!("A {:?}", get_const(A{})); println!("B {:?}", get_const(B{})); }
ただし、こういう使い方はできません。
trait HasConst2 { const C: usize; } struct A; struct B; impl HasConst2 for A { const C: usize = 1usize; } impl HasConst2 for B { const C: usize = 2usize; } fn gen_array<T: HasConst2>(_: T) { let array = [0i64; T::C]; println!("{:?}", array); }
型変数のassociated constは、constとしては扱われないようです。[0i64; A::C]
とかはOKです。ここはどうしてそうなっているのか、今ひとつ理解していません。
(全てのgenericsがinstantiateされるわけではないとかそういうことだろうか?)
感想
Rustで型クラスを使っていて不便だった点は、定数を返したいときにもわざわざ関数呼び出しにしなければならないところでした。(もちろん最適化は効くんでしょうが)(見よう見ようと思ってめんどくてアセンブラは読んでいない) そういう気持ち悪さを除いてくれる変更で、よい変更だったと思います。既存のコードを書き直す必要があるのがアレですが。。